Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm64/freescale/imx/imx_ccm.c
39536 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2020 Oleksandr Tymoshenko <[email protected]>
5
* Copyright (c) 2024 The FreeBSD Foundation
6
*
7
* Portions of this software were developed by Tom Jones <[email protected]>
8
* under sponsorship from the FreeBSD Foundation.
9
*
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
12
* are met:
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* SUCH DAMAGE.
30
*/
31
32
#include <sys/cdefs.h>
33
34
/*
35
* Clock Control Module driver for Freescale i.MX 8M SoC family.
36
*/
37
38
#include <sys/param.h>
39
#include <sys/systm.h>
40
#include <sys/kernel.h>
41
#include <sys/module.h>
42
#include <sys/mutex.h>
43
#include <sys/bus.h>
44
#include <sys/rman.h>
45
46
#include <dev/ofw/ofw_bus.h>
47
#include <dev/ofw/ofw_bus_subr.h>
48
49
#include <machine/bus.h>
50
51
#include <arm64/freescale/imx/imx_ccm.h>
52
#include <arm64/freescale/imx/clk/imx_clk_gate.h>
53
#include <arm64/freescale/imx/clk/imx_clk_mux.h>
54
#include <arm64/freescale/imx/clk/imx_clk_composite.h>
55
#include <arm64/freescale/imx/clk/imx_clk_sscg_pll.h>
56
#include <arm64/freescale/imx/clk/imx_clk_frac_pll.h>
57
58
#include "clkdev_if.h"
59
60
static inline uint32_t
61
CCU_READ4(struct imx_ccm_softc *sc, bus_size_t off)
62
{
63
64
return (bus_read_4(sc->mem_res, off));
65
}
66
67
static inline void
68
CCU_WRITE4(struct imx_ccm_softc *sc, bus_size_t off, uint32_t val)
69
{
70
71
bus_write_4(sc->mem_res, off, val);
72
}
73
74
int
75
imx_ccm_detach(device_t dev)
76
{
77
struct imx_ccm_softc *sc;
78
79
sc = device_get_softc(dev);
80
81
if (sc->mem_res != NULL)
82
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
83
84
return (0);
85
}
86
87
int
88
imx_ccm_attach(device_t dev)
89
{
90
struct imx_ccm_softc *sc;
91
int err, rid;
92
phandle_t node;
93
int i;
94
95
sc = device_get_softc(dev);
96
sc->dev = dev;
97
err = 0;
98
99
/* Allocate bus_space resources. */
100
rid = 0;
101
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
102
RF_ACTIVE);
103
if (sc->mem_res == NULL) {
104
device_printf(dev, "Cannot allocate memory resources\n");
105
err = ENXIO;
106
goto out;
107
}
108
109
mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
110
111
sc->clkdom = clkdom_create(dev);
112
if (sc->clkdom == NULL)
113
panic("Cannot create clkdom\n");
114
115
for (i = 0; i < sc->nclks; i++) {
116
switch (sc->clks[i].type) {
117
case IMX_CLK_UNDEFINED:
118
break;
119
case IMX_CLK_LINK:
120
clknode_link_register(sc->clkdom,
121
sc->clks[i].clk.link);
122
break;
123
case IMX_CLK_FIXED:
124
clknode_fixed_register(sc->clkdom,
125
sc->clks[i].clk.fixed);
126
break;
127
case IMX_CLK_MUX:
128
imx_clk_mux_register(sc->clkdom, sc->clks[i].clk.mux);
129
break;
130
case IMX_CLK_GATE:
131
imx_clk_gate_register(sc->clkdom, sc->clks[i].clk.gate);
132
break;
133
case IMX_CLK_COMPOSITE:
134
imx_clk_composite_register(sc->clkdom, sc->clks[i].clk.composite);
135
break;
136
case IMX_CLK_SSCG_PLL:
137
imx_clk_sscg_pll_register(sc->clkdom, sc->clks[i].clk.sscg_pll);
138
break;
139
case IMX_CLK_FRAC_PLL:
140
imx_clk_frac_pll_register(sc->clkdom, sc->clks[i].clk.frac_pll);
141
break;
142
case IMX_CLK_DIV:
143
clknode_div_register(sc->clkdom, sc->clks[i].clk.div);
144
break;
145
default:
146
device_printf(dev, "Unknown clock type %d\n", sc->clks[i].type);
147
return (ENXIO);
148
}
149
}
150
151
if (clkdom_finit(sc->clkdom) != 0)
152
panic("cannot finalize clkdom initialization\n");
153
154
if (bootverbose)
155
clkdom_dump(sc->clkdom);
156
157
node = ofw_bus_get_node(dev);
158
clk_set_assigned(dev, node);
159
160
err = 0;
161
162
out:
163
164
if (err != 0)
165
imx_ccm_detach(dev);
166
167
return (err);
168
}
169
170
static int
171
imx_ccm_write_4(device_t dev, bus_addr_t addr, uint32_t val)
172
{
173
struct imx_ccm_softc *sc;
174
175
sc = device_get_softc(dev);
176
CCU_WRITE4(sc, addr, val);
177
return (0);
178
}
179
180
static int
181
imx_ccm_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
182
{
183
struct imx_ccm_softc *sc;
184
185
sc = device_get_softc(dev);
186
187
*val = CCU_READ4(sc, addr);
188
return (0);
189
}
190
191
static int
192
imx_ccm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set)
193
{
194
struct imx_ccm_softc *sc;
195
uint32_t reg;
196
197
sc = device_get_softc(dev);
198
199
reg = CCU_READ4(sc, addr);
200
reg &= ~clr;
201
reg |= set;
202
CCU_WRITE4(sc, addr, reg);
203
204
return (0);
205
}
206
207
static void
208
imx_ccm_device_lock(device_t dev)
209
{
210
struct imx_ccm_softc *sc;
211
212
sc = device_get_softc(dev);
213
mtx_lock(&sc->mtx);
214
}
215
216
static void
217
imx_ccm_device_unlock(device_t dev)
218
{
219
struct imx_ccm_softc *sc;
220
221
sc = device_get_softc(dev);
222
mtx_unlock(&sc->mtx);
223
}
224
225
static device_method_t imx_ccm_methods[] = {
226
/* clkdev interface */
227
DEVMETHOD(clkdev_write_4, imx_ccm_write_4),
228
DEVMETHOD(clkdev_read_4, imx_ccm_read_4),
229
DEVMETHOD(clkdev_modify_4, imx_ccm_modify_4),
230
DEVMETHOD(clkdev_device_lock, imx_ccm_device_lock),
231
DEVMETHOD(clkdev_device_unlock, imx_ccm_device_unlock),
232
233
DEVMETHOD_END
234
};
235
236
DEFINE_CLASS_0(imx_ccm, imx_ccm_driver, imx_ccm_methods,
237
sizeof(struct imx_ccm_softc));
238
239