1f21c469dSHubert Mazur /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3f21c469dSHubert Mazur *
4f21c469dSHubert Mazur * Copyright (c) 2021 Semihalf.
5f21c469dSHubert Mazur *
6f21c469dSHubert Mazur * Redistribution and use in source and binary forms, with or without
7f21c469dSHubert Mazur * modification, are permitted provided that the following conditions
8f21c469dSHubert Mazur * are met:
9f21c469dSHubert Mazur * 1. Redistributions of source code must retain the above copyright
10f21c469dSHubert Mazur * notice, this list of conditions and the following disclaimer.
11f21c469dSHubert Mazur * 2. Redistributions in binary form must reproduce the above copyright
12f21c469dSHubert Mazur * notice, this list of conditions and the following disclaimer in the
13f21c469dSHubert Mazur * documentation and/or other materials provided with the distribution.
14f21c469dSHubert Mazur *
15f21c469dSHubert Mazur * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16f21c469dSHubert Mazur * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17f21c469dSHubert Mazur * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18f21c469dSHubert Mazur * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19f21c469dSHubert Mazur * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20f21c469dSHubert Mazur * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21f21c469dSHubert Mazur * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22f21c469dSHubert Mazur * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23f21c469dSHubert Mazur * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24f21c469dSHubert Mazur * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25f21c469dSHubert Mazur * SUCH DAMAGE.
26f21c469dSHubert Mazur */
27f21c469dSHubert Mazur
28f21c469dSHubert Mazur #include <sys/param.h>
29f21c469dSHubert Mazur #include <sys/bus.h>
30f21c469dSHubert Mazur #include <sys/kernel.h>
31f21c469dSHubert Mazur #include <sys/module.h>
32f21c469dSHubert Mazur #include <sys/mutex.h>
33f21c469dSHubert Mazur #include <sys/rman.h>
34f21c469dSHubert Mazur #include <machine/bus.h>
35f21c469dSHubert Mazur
36f21c469dSHubert Mazur #include <dev/fdt/simplebus.h>
37f21c469dSHubert Mazur
38*be82b3a0SEmmanuel Vadot #include <dev/clk/clk.h>
39*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_fixed.h>
40f21c469dSHubert Mazur
41f21c469dSHubert Mazur #include <dev/ofw/ofw_bus.h>
42f21c469dSHubert Mazur #include <dev/ofw/ofw_bus_subr.h>
43f21c469dSHubert Mazur
44f21c469dSHubert Mazur #include "clkdev_if.h"
45f21c469dSHubert Mazur #include "periph.h"
46f21c469dSHubert Mazur
47f21c469dSHubert Mazur #define TBG_COUNT 4
48f21c469dSHubert Mazur #define XTAL_OFW_INDEX 4
49f21c469dSHubert Mazur
50f21c469dSHubert Mazur static struct resource_spec a37x0_periph_clk_spec[] = {
51f21c469dSHubert Mazur { SYS_RES_MEMORY, 0, RF_ACTIVE },
52f21c469dSHubert Mazur { -1, 0 }
53f21c469dSHubert Mazur };
54f21c469dSHubert Mazur
55f21c469dSHubert Mazur int
a37x0_periph_clk_attach(device_t dev)56f21c469dSHubert Mazur a37x0_periph_clk_attach(device_t dev)
57f21c469dSHubert Mazur {
58f21c469dSHubert Mazur struct a37x0_periph_clknode_def *dev_defs;
59f21c469dSHubert Mazur struct a37x0_periph_clk_softc *sc;
60f21c469dSHubert Mazur const char *tbg_clocks[5];
61f21c469dSHubert Mazur const char *xtal_clock;
62f21c469dSHubert Mazur phandle_t node;
63f21c469dSHubert Mazur int error, i;
64f21c469dSHubert Mazur clk_t clock;
65f21c469dSHubert Mazur
66f21c469dSHubert Mazur sc = device_get_softc(dev);
67f21c469dSHubert Mazur node = ofw_bus_get_node(dev);
68f21c469dSHubert Mazur sc->dev = dev;
69f21c469dSHubert Mazur
70f21c469dSHubert Mazur mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
71f21c469dSHubert Mazur
72f21c469dSHubert Mazur if (bus_alloc_resources(dev, a37x0_periph_clk_spec, &sc->res) != 0) {
73f21c469dSHubert Mazur device_printf(dev, "Cannot allocate resources\n");
74f21c469dSHubert Mazur return (ENXIO);
75f21c469dSHubert Mazur }
76f21c469dSHubert Mazur
77f21c469dSHubert Mazur sc->clkdom = clkdom_create(dev);
78f21c469dSHubert Mazur if (sc->clkdom == NULL) {
79f21c469dSHubert Mazur device_printf(dev, "Cannot create clock domain\n");
80f21c469dSHubert Mazur return (ENXIO);
81f21c469dSHubert Mazur }
82f21c469dSHubert Mazur
83f21c469dSHubert Mazur for (i = 0; i < TBG_COUNT; i++){
84f21c469dSHubert Mazur error = clk_get_by_ofw_index(dev, node, i, &clock);
85f21c469dSHubert Mazur if (error)
86f21c469dSHubert Mazur goto fail;
87f21c469dSHubert Mazur tbg_clocks[i] = clk_get_name(clock);
88f21c469dSHubert Mazur }
89f21c469dSHubert Mazur
90f21c469dSHubert Mazur error = clk_get_by_ofw_index(dev, node, XTAL_OFW_INDEX, &clock);
91f21c469dSHubert Mazur if (error)
92f21c469dSHubert Mazur goto fail;
93f21c469dSHubert Mazur xtal_clock = clk_get_name(clock);
94f21c469dSHubert Mazur
95f21c469dSHubert Mazur dev_defs = sc->devices;
96f21c469dSHubert Mazur
97f21c469dSHubert Mazur for (i = 0; i< sc->device_count; i++) {
98f21c469dSHubert Mazur dev_defs[i].common_def.tbgs = tbg_clocks;
99f21c469dSHubert Mazur dev_defs[i].common_def.xtal = xtal_clock;
100f21c469dSHubert Mazur dev_defs[i].common_def.tbg_cnt = TBG_COUNT;
101f21c469dSHubert Mazur switch (dev_defs[i].type) {
102f21c469dSHubert Mazur case CLK_FULL_DD:
103f21c469dSHubert Mazur error = a37x0_periph_d_register_full_clk_dd(
104f21c469dSHubert Mazur sc->clkdom, &dev_defs[i]);
105f21c469dSHubert Mazur if (error)
106f21c469dSHubert Mazur goto fail;
107f21c469dSHubert Mazur break;
108f21c469dSHubert Mazur
109f21c469dSHubert Mazur case CLK_FULL:
110f21c469dSHubert Mazur error = a37x0_periph_d_register_full_clk(
111f21c469dSHubert Mazur sc->clkdom, &dev_defs[i]);
112f21c469dSHubert Mazur if (error)
113f21c469dSHubert Mazur goto fail;
114f21c469dSHubert Mazur break;
115f21c469dSHubert Mazur
116f21c469dSHubert Mazur case CLK_GATE:
117f21c469dSHubert Mazur error = a37x0_periph_gate_register_gate(
118f21c469dSHubert Mazur sc->clkdom, &dev_defs[i]);
119f21c469dSHubert Mazur if (error)
120f21c469dSHubert Mazur goto fail;
121f21c469dSHubert Mazur break;
122f21c469dSHubert Mazur
123f21c469dSHubert Mazur case CLK_MUX_GATE:
124f21c469dSHubert Mazur error = a37x0_periph_register_mux_gate(
125f21c469dSHubert Mazur sc->clkdom, &dev_defs[i]);
126f21c469dSHubert Mazur if (error)
127f21c469dSHubert Mazur goto fail;
128f21c469dSHubert Mazur break;
129f21c469dSHubert Mazur
130f21c469dSHubert Mazur case CLK_FIXED:
131f21c469dSHubert Mazur error = a37x0_periph_fixed_register_fixed(
132f21c469dSHubert Mazur sc->clkdom, &dev_defs[i]);
133f21c469dSHubert Mazur if (error)
134f21c469dSHubert Mazur goto fail;
135f21c469dSHubert Mazur break;
136f21c469dSHubert Mazur
137f21c469dSHubert Mazur case CLK_CPU:
138f21c469dSHubert Mazur error = a37x0_periph_d_register_periph_cpu(
139f21c469dSHubert Mazur sc->clkdom, &dev_defs[i]);
140f21c469dSHubert Mazur if (error)
141f21c469dSHubert Mazur goto fail;
142f21c469dSHubert Mazur break;
143f21c469dSHubert Mazur
144f21c469dSHubert Mazur case CLK_MDD:
145f21c469dSHubert Mazur error = a37x0_periph_d_register_mdd(
146f21c469dSHubert Mazur sc->clkdom, &dev_defs[i]);
147f21c469dSHubert Mazur if (error)
148f21c469dSHubert Mazur goto fail;
149f21c469dSHubert Mazur break;
150f21c469dSHubert Mazur
151f21c469dSHubert Mazur case CLK_MUX_GATE_FIXED:
152f21c469dSHubert Mazur error = a37x0_periph_register_mux_gate_fixed(
153f21c469dSHubert Mazur sc->clkdom, &dev_defs[i]);
154f21c469dSHubert Mazur if (error)
155f21c469dSHubert Mazur goto fail;
156f21c469dSHubert Mazur break;
157f21c469dSHubert Mazur
158f21c469dSHubert Mazur default:
159f21c469dSHubert Mazur return (ENXIO);
160f21c469dSHubert Mazur }
161f21c469dSHubert Mazur }
162f21c469dSHubert Mazur
163f21c469dSHubert Mazur error = clkdom_finit(sc->clkdom);
164f21c469dSHubert Mazur if (error)
165f21c469dSHubert Mazur goto fail;
166f21c469dSHubert Mazur
167f21c469dSHubert Mazur if (bootverbose)
168f21c469dSHubert Mazur clkdom_dump(sc->clkdom);
169f21c469dSHubert Mazur
170f21c469dSHubert Mazur return (0);
171f21c469dSHubert Mazur
172f21c469dSHubert Mazur fail:
173f21c469dSHubert Mazur bus_release_resources(dev, a37x0_periph_clk_spec, &sc->res);
174f21c469dSHubert Mazur
175f21c469dSHubert Mazur return (error);
176f21c469dSHubert Mazur
177f21c469dSHubert Mazur }
178f21c469dSHubert Mazur
179f21c469dSHubert Mazur int
a37x0_periph_clk_read_4(device_t dev,bus_addr_t addr,uint32_t * val)180f21c469dSHubert Mazur a37x0_periph_clk_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
181f21c469dSHubert Mazur {
182f21c469dSHubert Mazur struct a37x0_periph_clk_softc *sc;
183f21c469dSHubert Mazur
184f21c469dSHubert Mazur sc = device_get_softc(dev);
185f21c469dSHubert Mazur *val = bus_read_4(sc->res, addr);
186f21c469dSHubert Mazur
187f21c469dSHubert Mazur return (0);
188f21c469dSHubert Mazur }
189f21c469dSHubert Mazur
190f21c469dSHubert Mazur void
a37x0_periph_clk_device_lock(device_t dev)191f21c469dSHubert Mazur a37x0_periph_clk_device_lock(device_t dev)
192f21c469dSHubert Mazur {
193f21c469dSHubert Mazur struct a37x0_periph_clk_softc *sc;
194f21c469dSHubert Mazur
195f21c469dSHubert Mazur sc = device_get_softc(dev);
196f21c469dSHubert Mazur mtx_lock(&sc->mtx);
197f21c469dSHubert Mazur }
198f21c469dSHubert Mazur
199f21c469dSHubert Mazur void
a37x0_periph_clk_device_unlock(device_t dev)200f21c469dSHubert Mazur a37x0_periph_clk_device_unlock(device_t dev)
201f21c469dSHubert Mazur {
202f21c469dSHubert Mazur struct a37x0_periph_clk_softc *sc;
203f21c469dSHubert Mazur
204f21c469dSHubert Mazur sc = device_get_softc(dev);
205f21c469dSHubert Mazur mtx_unlock(&sc->mtx);
206f21c469dSHubert Mazur }
207f21c469dSHubert Mazur
208f21c469dSHubert Mazur int
a37x0_periph_clk_detach(device_t dev)209f21c469dSHubert Mazur a37x0_periph_clk_detach(device_t dev)
210f21c469dSHubert Mazur {
211f21c469dSHubert Mazur
212f21c469dSHubert Mazur return (EBUSY);
213f21c469dSHubert Mazur }
214