Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm64/qoriq/clk/lx2160a_clkgen.c
39536 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright 2020 Michal Meloun <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <sys/cdefs.h>
29
/*
30
* Clock driver for LX2160A SoC.
31
*/
32
#include <sys/param.h>
33
#include <sys/bus.h>
34
#include <sys/kernel.h>
35
#include <sys/module.h>
36
#include <sys/mutex.h>
37
#include <sys/rman.h>
38
#include <machine/bus.h>
39
40
#include <dev/fdt/simplebus.h>
41
42
#include <dev/ofw/ofw_bus.h>
43
#include <dev/ofw/ofw_bus_subr.h>
44
45
#include <dev/clk/clk_fixed.h>
46
47
#include <arm64/qoriq/clk/qoriq_clkgen.h>
48
49
#define PLL(_id1, _id2, cname, o, d) \
50
{ \
51
.clkdef.id = QORIQ_CLK_ID(_id1, _id2), \
52
.clkdef.name = cname, \
53
.clkdef.flags = 0, \
54
.offset = o, \
55
.shift = 1, \
56
.mask = 0xFE, \
57
.dividers = d, \
58
.flags = QORIQ_CLK_PLL_HAS_KILL_BIT, \
59
}
60
61
static const uint8_t plt_divs[] =
62
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0};
63
static const uint8_t cga_divs[] = {2, 4, 0};
64
static const uint8_t cgb_divs[] = {2, 3, 4, 0};
65
66
static struct qoriq_clk_pll_def pltfrm_pll =
67
PLL(QORIQ_TYPE_PLATFORM_PLL, 0, "platform_pll", 0x60080, plt_divs);
68
static struct qoriq_clk_pll_def cga_pll1 =
69
PLL(QORIQ_TYPE_INTERNAL, 0, "cga_pll1", 0x80, cga_divs);
70
static struct qoriq_clk_pll_def cga_pll2 =
71
PLL(QORIQ_TYPE_INTERNAL, 0, "cga_pll2", 0xA0, cga_divs);
72
static struct qoriq_clk_pll_def cgb_pll1 =
73
PLL(QORIQ_TYPE_INTERNAL, 0, "cgb_pll1", 0x10080, cgb_divs);
74
static struct qoriq_clk_pll_def cgb_pll2 =
75
PLL(QORIQ_TYPE_INTERNAL, 0, "cgb_pll2", 0x100A0, cgb_divs);
76
77
static struct qoriq_clk_pll_def *cg_plls[] = {
78
&cga_pll1,
79
&cga_pll2,
80
&cgb_pll1,
81
&cgb_pll2,
82
};
83
84
#if 0
85
static struct qoriq_clk_pll_def *cg_plls[] = {
86
&(struct qoriq_clk_pll_def)
87
{PLL(QORIQ_TYPE_INTERNAL, 0, "cga_pll1", 0x80, cg_divs)},
88
&(struct qoriq_clk_pll_def)
89
{PLL(QORIQ_TYPE_INTERNAL, 0, "cga_pll2", 0xA0, cg_divs)},
90
&(struct qoriq_clk_pll_def)
91
{PLL(QORIQ_TYPE_INTERNAL, 0, "cgb_pll1", 0x10080, cg_divs)},
92
&(struct qoriq_clk_pll_def)
93
{PLL(QORIQ_TYPE_INTERNAL, 0, "cgb_pll2", 0x100A0, cg_divs)},
94
};
95
#endif
96
97
static const char *cmuxa_plist[] = {
98
"cga_pll1",
99
"cga_pll1_div2",
100
"cga_pll1_div4",
101
NULL,
102
"cga_pll2",
103
"cga_pll2_div2",
104
"cga_pll2_div4",
105
};
106
107
static const char *cmuxb_plist[] = {
108
"cgb_pll1",
109
"cgb_pll1_div2",
110
"cgb_pll1_div4",
111
NULL,
112
"cgb_pll2",
113
"cgb_pll2_div2",
114
"cgb_pll2_div4",
115
};
116
117
#define MUX(_id1, _id2, cname, plist, o) \
118
{ \
119
.clkdef.id = QORIQ_CLK_ID(_id1, _id2), \
120
.clkdef.name = cname, \
121
.clkdef.parent_names = plist, \
122
.clkdef.parent_cnt = nitems(plist), \
123
.clkdef.flags = 0, \
124
.offset = o, \
125
.width = 4, \
126
.shift = 27, \
127
.mux_flags = 0, \
128
}
129
static struct clk_mux_def cmux0 =
130
MUX(QORIQ_TYPE_CMUX, 0, "cg-cmux0", cmuxa_plist, 0x70000);
131
static struct clk_mux_def cmux1 =
132
MUX(QORIQ_TYPE_CMUX, 1, "cg-cmux1", cmuxa_plist, 0x70020);
133
static struct clk_mux_def cmux2 =
134
MUX(QORIQ_TYPE_CMUX, 2, "cg-cmux2", cmuxa_plist, 0x70040);
135
static struct clk_mux_def cmux3 =
136
MUX(QORIQ_TYPE_CMUX, 3, "cg-cmux3", cmuxa_plist, 0x70060);
137
static struct clk_mux_def cmux4 =
138
MUX(QORIQ_TYPE_CMUX, 4, "cg-cmux4", cmuxb_plist, 0x70080);
139
static struct clk_mux_def cmux5 =
140
MUX(QORIQ_TYPE_CMUX, 5, "cg-cmux5", cmuxb_plist, 0x700A0);
141
static struct clk_mux_def cmux6 =
142
MUX(QORIQ_TYPE_CMUX, 6, "cg-cmux6", cmuxb_plist, 0x700C0);
143
static struct clk_mux_def cmux7 =
144
MUX(QORIQ_TYPE_CMUX, 7, "cg-cmux7", cmuxb_plist, 0x700E0);
145
146
static struct clk_mux_def *mux_nodes[] = {
147
&cmux0,
148
&cmux1,
149
&cmux2,
150
&cmux3,
151
&cmux4,
152
&cmux5,
153
&cmux6,
154
&cmux7,
155
};
156
157
static int
158
lx2160a_clkgen_probe(device_t dev)
159
{
160
161
if (!ofw_bus_status_okay(dev))
162
return (ENXIO);
163
164
if(!ofw_bus_is_compatible(dev, "fsl,lx2160a-clockgen"))
165
return (ENXIO);
166
167
device_set_desc(dev, "LX2160A clockgen");
168
return (BUS_PROBE_DEFAULT);
169
}
170
171
static int
172
lx2160a_clkgen_attach(device_t dev)
173
{
174
struct qoriq_clkgen_softc *sc;
175
int rv;
176
177
sc = device_get_softc(dev);
178
179
sc->pltfrm_pll_def = &pltfrm_pll;
180
sc->cga_pll = cg_plls;
181
sc->cga_pll_num = nitems(cg_plls);
182
sc->mux = mux_nodes;
183
sc->mux_num = nitems(mux_nodes);
184
sc->flags = QORIQ_LITTLE_ENDIAN;
185
186
rv = qoriq_clkgen_attach(dev);
187
188
printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x00080, bus_read_4(sc->res, 0x00080));
189
printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x000A0, bus_read_4(sc->res, 0x000A0));
190
printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x10080, bus_read_4(sc->res, 0x10080));
191
printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x100A0, bus_read_4(sc->res, 0x100A0));
192
printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x60080, bus_read_4(sc->res, 0x60080));
193
printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x600A0, bus_read_4(sc->res, 0x600A0));
194
return (rv);
195
}
196
197
static device_method_t lx2160a_clkgen_methods[] = {
198
DEVMETHOD(device_probe, lx2160a_clkgen_probe),
199
DEVMETHOD(device_attach, lx2160a_clkgen_attach),
200
201
DEVMETHOD_END
202
};
203
204
DEFINE_CLASS_1(lx2160a_clkgen, lx2160a_clkgen_driver, lx2160a_clkgen_methods,
205
sizeof(struct qoriq_clkgen_softc), qoriq_clkgen_driver);
206
EARLY_DRIVER_MODULE(lx2160a_clkgen, simplebus, lx2160a_clkgen_driver, 0, 0,
207
BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
208
209