xref: /freebsd/sys/arm/mv/clk/a37x0_periph_clk_driver.c (revision be82b3a0bf72ed3b5f01ac9fcd8dcd3802e3c742)
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