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