1cb3c3e0aSEmmanuel Vadot /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3cb3c3e0aSEmmanuel Vadot *
4cb3c3e0aSEmmanuel Vadot * Copyright (c) 2018-2021 Emmanuel Vadot <manu@FreeBSD.org>
5cb3c3e0aSEmmanuel Vadot * Copyright (c) 2021 Bjoern A. Zeeb <bz@FreeBSD.org>
6cb3c3e0aSEmmanuel Vadot *
7cb3c3e0aSEmmanuel Vadot * Redistribution and use in source and binary forms, with or without
8cb3c3e0aSEmmanuel Vadot * modification, are permitted provided that the following conditions
9cb3c3e0aSEmmanuel Vadot * are met:
10cb3c3e0aSEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright
11cb3c3e0aSEmmanuel Vadot * notice, this list of conditions and the following disclaimer.
12cb3c3e0aSEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright
13cb3c3e0aSEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the
14cb3c3e0aSEmmanuel Vadot * documentation and/or other materials provided with the distribution.
15cb3c3e0aSEmmanuel Vadot *
16cb3c3e0aSEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17cb3c3e0aSEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18cb3c3e0aSEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19cb3c3e0aSEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20cb3c3e0aSEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21cb3c3e0aSEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22cb3c3e0aSEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23cb3c3e0aSEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24cb3c3e0aSEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25cb3c3e0aSEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26cb3c3e0aSEmmanuel Vadot * SUCH DAMAGE.
27cb3c3e0aSEmmanuel Vadot */
28cb3c3e0aSEmmanuel Vadot
29cb3c3e0aSEmmanuel Vadot #include <sys/param.h>
30cb3c3e0aSEmmanuel Vadot #include <sys/bus.h>
31cb3c3e0aSEmmanuel Vadot #include <sys/systm.h>
32cb3c3e0aSEmmanuel Vadot #include <sys/clock.h>
33cb3c3e0aSEmmanuel Vadot
34cb3c3e0aSEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
35cb3c3e0aSEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
36cb3c3e0aSEmmanuel Vadot
37*be82b3a0SEmmanuel Vadot #include <dev/clk/clk.h>
38cb3c3e0aSEmmanuel Vadot
39cb3c3e0aSEmmanuel Vadot #include <dev/iicbus/pmic/rockchip/rk8xx.h>
40cb3c3e0aSEmmanuel Vadot
41cb3c3e0aSEmmanuel Vadot /* Clock class and method */
42cb3c3e0aSEmmanuel Vadot struct rk8xx_clk_sc {
43cb3c3e0aSEmmanuel Vadot device_t base_dev;
44cb3c3e0aSEmmanuel Vadot };
45cb3c3e0aSEmmanuel Vadot
46cb3c3e0aSEmmanuel Vadot #define CLK32OUT_REG 0x20
47cb3c3e0aSEmmanuel Vadot #define CLK32OUT_CLKOUT2_EN 1
48cb3c3e0aSEmmanuel Vadot
49cb3c3e0aSEmmanuel Vadot static int
rk8xx_clk_set_gate_1(struct clknode * clk,bool enable)50cb3c3e0aSEmmanuel Vadot rk8xx_clk_set_gate_1(struct clknode *clk, bool enable)
51cb3c3e0aSEmmanuel Vadot {
52cb3c3e0aSEmmanuel Vadot struct rk8xx_clk_sc *sc;
53cb3c3e0aSEmmanuel Vadot uint8_t val;
54cb3c3e0aSEmmanuel Vadot
55cb3c3e0aSEmmanuel Vadot sc = clknode_get_softc(clk);
56cb3c3e0aSEmmanuel Vadot
57cb3c3e0aSEmmanuel Vadot rk8xx_read(sc->base_dev, CLK32OUT_REG, &val, sizeof(val));
58cb3c3e0aSEmmanuel Vadot if (enable)
59cb3c3e0aSEmmanuel Vadot val |= CLK32OUT_CLKOUT2_EN;
60cb3c3e0aSEmmanuel Vadot else
61cb3c3e0aSEmmanuel Vadot val &= ~CLK32OUT_CLKOUT2_EN;
62cb3c3e0aSEmmanuel Vadot rk8xx_write(sc->base_dev, CLK32OUT_REG, &val, 1);
63cb3c3e0aSEmmanuel Vadot
64cb3c3e0aSEmmanuel Vadot return (0);
65cb3c3e0aSEmmanuel Vadot }
66cb3c3e0aSEmmanuel Vadot
67cb3c3e0aSEmmanuel Vadot static int
rk8xx_clk_recalc(struct clknode * clk,uint64_t * freq)68cb3c3e0aSEmmanuel Vadot rk8xx_clk_recalc(struct clknode *clk, uint64_t *freq)
69cb3c3e0aSEmmanuel Vadot {
70cb3c3e0aSEmmanuel Vadot
71cb3c3e0aSEmmanuel Vadot *freq = 32768;
72cb3c3e0aSEmmanuel Vadot return (0);
73cb3c3e0aSEmmanuel Vadot }
74cb3c3e0aSEmmanuel Vadot
75cb3c3e0aSEmmanuel Vadot static clknode_method_t rk8xx_clk_clknode_methods_0[] = {
76cb3c3e0aSEmmanuel Vadot CLKNODEMETHOD(clknode_recalc_freq, rk8xx_clk_recalc),
77cb3c3e0aSEmmanuel Vadot CLKNODEMETHOD_END
78cb3c3e0aSEmmanuel Vadot };
79cb3c3e0aSEmmanuel Vadot
80cb3c3e0aSEmmanuel Vadot DEFINE_CLASS_1(rk8xx_clk_clknode_0, rk8xx_clk_clknode_class_0,
81cb3c3e0aSEmmanuel Vadot rk8xx_clk_clknode_methods_0, sizeof(struct rk8xx_clk_sc),
82cb3c3e0aSEmmanuel Vadot clknode_class);
83cb3c3e0aSEmmanuel Vadot
84cb3c3e0aSEmmanuel Vadot static clknode_method_t rk8xx_clk_clknode_methods_1[] = {
85cb3c3e0aSEmmanuel Vadot CLKNODEMETHOD(clknode_set_gate, rk8xx_clk_set_gate_1),
86cb3c3e0aSEmmanuel Vadot CLKNODEMETHOD_END
87cb3c3e0aSEmmanuel Vadot };
88cb3c3e0aSEmmanuel Vadot
89cb3c3e0aSEmmanuel Vadot DEFINE_CLASS_1(rk8xx_clk_clknode_1, rk8xx_clk_clknode_class_1,
90cb3c3e0aSEmmanuel Vadot rk8xx_clk_clknode_methods_1, sizeof(struct rk8xx_clk_sc),
91cb3c3e0aSEmmanuel Vadot rk8xx_clk_clknode_class_0);
92cb3c3e0aSEmmanuel Vadot
93cb3c3e0aSEmmanuel Vadot int
rk8xx_attach_clocks(struct rk8xx_softc * sc)9498c60dc3SEmmanuel Vadot rk8xx_attach_clocks(struct rk8xx_softc *sc)
95cb3c3e0aSEmmanuel Vadot {
96cb3c3e0aSEmmanuel Vadot struct clkdom *clkdom;
97cb3c3e0aSEmmanuel Vadot struct clknode_init_def clkidef;
98cb3c3e0aSEmmanuel Vadot struct clknode *clk;
99cb3c3e0aSEmmanuel Vadot struct rk8xx_clk_sc *clksc;
100cb3c3e0aSEmmanuel Vadot const char **clknames;
101cb3c3e0aSEmmanuel Vadot phandle_t node;
102cb3c3e0aSEmmanuel Vadot int nclks, rv;
103cb3c3e0aSEmmanuel Vadot
10498c60dc3SEmmanuel Vadot node = ofw_bus_get_node(sc->dev);
105cb3c3e0aSEmmanuel Vadot
106cb3c3e0aSEmmanuel Vadot /* clock-output-names are optional. Could use them for clkidef.name. */
107cb3c3e0aSEmmanuel Vadot nclks = ofw_bus_string_list_to_array(node, "clock-output-names",
108cb3c3e0aSEmmanuel Vadot &clknames);
109cb3c3e0aSEmmanuel Vadot
11098c60dc3SEmmanuel Vadot clkdom = clkdom_create(sc->dev);
111cb3c3e0aSEmmanuel Vadot
112cb3c3e0aSEmmanuel Vadot memset(&clkidef, 0, sizeof(clkidef));
113cb3c3e0aSEmmanuel Vadot clkidef.id = 0;
11466946511SEmmanuel Vadot clkidef.name = (nclks == 2) ? clknames[0] : "clk32kout1";
115cb3c3e0aSEmmanuel Vadot clk = clknode_create(clkdom, &rk8xx_clk_clknode_class_0, &clkidef);
116cb3c3e0aSEmmanuel Vadot if (clk == NULL) {
11798c60dc3SEmmanuel Vadot device_printf(sc->dev, "Cannot create '%s'.\n", clkidef.name);
118cb3c3e0aSEmmanuel Vadot return (ENXIO);
119cb3c3e0aSEmmanuel Vadot }
120cb3c3e0aSEmmanuel Vadot clksc = clknode_get_softc(clk);
12198c60dc3SEmmanuel Vadot clksc->base_dev = sc->dev;
122cb3c3e0aSEmmanuel Vadot clknode_register(clkdom, clk);
123cb3c3e0aSEmmanuel Vadot
124cb3c3e0aSEmmanuel Vadot memset(&clkidef, 0, sizeof(clkidef));
125cb3c3e0aSEmmanuel Vadot clkidef.id = 1;
12666946511SEmmanuel Vadot clkidef.name = (nclks == 2) ? clknames[1] : "clk32kout2";
127cb3c3e0aSEmmanuel Vadot clk = clknode_create(clkdom, &rk8xx_clk_clknode_class_1, &clkidef);
128cb3c3e0aSEmmanuel Vadot if (clk == NULL) {
12998c60dc3SEmmanuel Vadot device_printf(sc->dev, "Cannot create '%s'.\n", clkidef.name);
130cb3c3e0aSEmmanuel Vadot return (ENXIO);
131cb3c3e0aSEmmanuel Vadot }
132cb3c3e0aSEmmanuel Vadot clksc = clknode_get_softc(clk);
13398c60dc3SEmmanuel Vadot clksc->base_dev = sc->dev;
134cb3c3e0aSEmmanuel Vadot clknode_register(clkdom, clk);
135cb3c3e0aSEmmanuel Vadot
136cb3c3e0aSEmmanuel Vadot rv = clkdom_finit(clkdom);
137cb3c3e0aSEmmanuel Vadot if (rv != 0) {
13898c60dc3SEmmanuel Vadot device_printf(sc->dev, "Cannot finalize clkdom initialization: "
139cb3c3e0aSEmmanuel Vadot "%d\n", rv);
140cb3c3e0aSEmmanuel Vadot return (ENXIO);
141cb3c3e0aSEmmanuel Vadot }
142cb3c3e0aSEmmanuel Vadot
143cb3c3e0aSEmmanuel Vadot if (bootverbose)
144cb3c3e0aSEmmanuel Vadot clkdom_dump(clkdom);
145cb3c3e0aSEmmanuel Vadot
146cb3c3e0aSEmmanuel Vadot return (0);
147cb3c3e0aSEmmanuel Vadot }
148