Skip to content

Commit b047e16

Browse files
committed
evbarm/am18xx: add async-clk clkgate driver
1 parent e847e2a commit b047e16

3 files changed

Lines changed: 200 additions & 2 deletions

File tree

sys/arch/arm/ti/am18xx_aclk.c

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/* $NetBSD $ */
2+
3+
/*-
4+
* Copyright (c) 2026 The NetBSD Foundation, Inc.
5+
* All rights reserved.
6+
*
7+
* This code is derived from software contributed to The NetBSD Foundation
8+
* by Yuri Honegger.
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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20+
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29+
* POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
32+
/*
33+
* Drivers for the async clock gates in the syscfg block of the TI AM1808.
34+
*/
35+
36+
#include <sys/param.h>
37+
#include <sys/bus.h>
38+
#include <sys/cdefs.h>
39+
#include <sys/device.h>
40+
41+
#include <dev/clk/clk_backend.h>
42+
#include <dev/fdt/fdtvar.h>
43+
#include <dev/fdt/syscon.h>
44+
45+
#include <arm/fdt/arm_fdtvar.h>
46+
47+
struct am18xx_aclk_config {
48+
struct clk *clk; /* double wrap clk because the config must be const */
49+
uint32_t mask;
50+
};
51+
52+
struct am18xx_aclk_softc {
53+
struct clk_domain sc_clkdom;
54+
const struct am18xx_aclk_config *sc_config;
55+
struct clk *sc_parent_clk;
56+
};
57+
58+
static int am18xx_aclk_match(device_t, cfdata_t, void *);
59+
static void am18xx_aclk_attach(device_t, device_t, void *);
60+
static struct clk * am18xx_aclk_decode(device_t, int, const void *, size_t);
61+
static struct clk * am18xx_aclk_clk_get(void *, const char *);
62+
static u_int am18xx_aclk_clk_get_rate(void *, struct clk *);
63+
static struct clk * am18xx_aclk_clk_get_parent(void *, struct clk *);
64+
65+
CFATTACH_DECL_NEW(am18xxaclk, sizeof(struct am18xx_aclk_softc),
66+
am18xx_aclk_match, am18xx_aclk_attach, NULL, NULL);
67+
68+
#define AM18XX_ACLK_CFGCHIP3 0xC
69+
#define AM18XX_ACLK_CFGCHIP3_ASYNC3_CLKSRC __BIT(4)
70+
#define AM18XX_ACLK_CFGCHIP3_ASYNC1_CLKSRC __BIT(2)
71+
72+
static struct clk am18xx_aclk_async1_clk = {
73+
.name = "async1",
74+
.flags = 0
75+
};
76+
static struct clk am18xx_aclk_async3_clk = {
77+
.name = "async3",
78+
.flags = 0
79+
};
80+
81+
static const struct am18xx_aclk_config am18xx_aclk_async1_config = {
82+
.clk = &am18xx_aclk_async1_clk,
83+
.mask = AM18XX_ACLK_CFGCHIP3_ASYNC1_CLKSRC,
84+
};
85+
static const struct am18xx_aclk_config am18xx_aclk_async3_config = {
86+
.clk = &am18xx_aclk_async3_clk,
87+
.mask = AM18XX_ACLK_CFGCHIP3_ASYNC3_CLKSRC,
88+
};
89+
90+
static const struct fdtbus_clock_controller_func am18xx_aclk_clk_fdt_funcs = {
91+
.decode = am18xx_aclk_decode,
92+
};
93+
94+
static const struct clk_funcs am18xx_aclk_clk_funcs = {
95+
.get = am18xx_aclk_clk_get,
96+
.get_rate = am18xx_aclk_clk_get_rate,
97+
.get_parent = am18xx_aclk_clk_get_parent,
98+
};
99+
100+
static const struct device_compatible_entry compat_data[] = {
101+
{ .compat = "ti,da850-async1-clksrc",
102+
.data = &am18xx_aclk_async1_config },
103+
{ .compat = "ti,da850-async3-clksrc",
104+
.data = &am18xx_aclk_async3_config },
105+
DEVICE_COMPAT_EOL
106+
};
107+
108+
static struct clk *
109+
am18xx_aclk_clk_get(void *priv, const char *name)
110+
{
111+
struct am18xx_aclk_softc * const sc = priv;
112+
113+
if (strcmp(sc->sc_config->clk->name, name) == 0) {
114+
return sc->sc_config->clk;
115+
}
116+
117+
return NULL;
118+
}
119+
120+
static u_int
121+
am18xx_aclk_clk_get_rate(void *priv, struct clk *clkp)
122+
{
123+
struct am18xx_aclk_softc * const sc = priv;
124+
125+
return clk_get_rate(sc->sc_parent_clk);
126+
}
127+
128+
static struct clk *
129+
am18xx_aclk_clk_get_parent(void *priv, struct clk *clkp)
130+
{
131+
struct am18xx_aclk_softc * const sc = priv;
132+
133+
return sc->sc_parent_clk;
134+
}
135+
136+
static struct clk *
137+
am18xx_aclk_decode(device_t dev, int cc_phandle, const void *data, size_t len)
138+
{
139+
struct am18xx_aclk_softc * const sc = device_private(dev);
140+
141+
return sc->sc_config->clk;
142+
}
143+
144+
int
145+
am18xx_aclk_match(device_t parent, cfdata_t cf, void *aux)
146+
{
147+
struct fdt_attach_args * const faa = aux;
148+
149+
return of_compatible_match(faa->faa_phandle, compat_data);
150+
}
151+
152+
void
153+
am18xx_aclk_attach(device_t parent, device_t self, void *aux)
154+
{
155+
struct am18xx_aclk_softc * const sc = device_private(self);
156+
struct fdt_attach_args * const faa = aux;
157+
const int phandle = faa->faa_phandle;
158+
159+
sc->sc_config = of_compatible_lookup(phandle, compat_data)->data;
160+
161+
/* ensure we have a clock parent */
162+
sc->sc_parent_clk = fdtbus_clock_get_index(phandle, 0);
163+
if (sc->sc_parent_clk == NULL) {
164+
aprint_error(": couldn't get parent clock");
165+
return;
166+
}
167+
168+
/* ensure clock gate bits are as expected */
169+
struct syscon *syscon = fdtbus_syscon_lookup(OF_parent(phandle));
170+
if (syscon == NULL) {
171+
aprint_error(": couldn't get syscon registers\n");
172+
return;
173+
}
174+
syscon_lock(syscon);
175+
uint32_t cfgchip_reg3 = syscon_read_4(syscon, AM18XX_ACLK_CFGCHIP3);
176+
syscon_unlock(syscon);
177+
if ((cfgchip_reg3 & sc->sc_config->mask) != 0) {
178+
aprint_error(": unexpected clock gate bits\n");
179+
return;
180+
}
181+
182+
/* attach a clock controller */
183+
sc->sc_clkdom.name = device_xname(self);
184+
sc->sc_clkdom.funcs = &am18xx_aclk_clk_funcs;
185+
sc->sc_clkdom.priv = sc;
186+
187+
sc->sc_config->clk->domain = &sc->sc_clkdom;
188+
clk_attach(sc->sc_config->clk);
189+
190+
fdtbus_register_clock_controller(self, phandle, &am18xx_aclk_clk_fdt_funcs);
191+
192+
aprint_normal("\n");
193+
}

sys/arch/arm/ti/files.ti

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ device am18xxpllc: fdt_clock
7979
attach am18xxpllc at fdt
8080
file arch/arm/ti/am18xx_pllc.c am18xxpllc
8181

82+
device am18xxaclk: fdt_clock
83+
attach am18xxaclk at fdt
84+
file arch/arm/ti/am18xx_aclk.c am18xxaclk
85+
8286
# UART
8387
attach com at fdt with ti_com: ti_prcm
8488
file arch/arm/ti/ti_com.c ti_com needs-flag

sys/arch/evbarm/conf/GENERIC_V5

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ imx23apbdma* at fdt? pass 1 # NXP i.MX23 DMA controller
7373
# Clock Controllers
7474
imx23clkctrl* at fdt? pass 1 # i.MX23 clock controller
7575
am18xxpllc* at fdt? pass 2 # TI AM18XX pll controller
76+
am18xxaclk* at fdt? pass 3 # TI AM18XX async-clk clkgates
7677
am18xxpsc* at fdt? pass 4 # TI AM18XX power&sleep controller
7778

7879
# System Controller
@@ -104,8 +105,8 @@ imx23pctl* at fdt? pass 1 # imx23 pin control+gpio
104105
gpio* at gpiobus?
105106

106107
# UART
107-
com* at fdt? pass 4 # UART
108-
plcom* at fdt? pass 4 # ARM PL011 UART
108+
com* at fdt? pass 5 # UART
109+
plcom* at fdt? pass 5 # ARM PL011 UART
109110

110111
# Various
111112
imx23digctl* at fdt? pass 1 # i.MX23 digctl block

0 commit comments

Comments
 (0)