1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
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 ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * 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 * $FreeBSD$
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/malloc.h>
37
38 #include <dev/extres/clk/clk.h>
39
40 #include <arm/ti/clk/ti_clk_clkctrl.h>
41
42 #include "clkdev_if.h"
43
44 #if 0
45 #define DPRINTF(dev, msg...) device_printf(dev, msg)
46 #else
47 #define DPRINTF(dev, msg...)
48 #endif
49
50 /*
51 * clknode for clkctrl, implements gate and mux (for gpioc)
52 */
53
54 #define GPIO_X_GDBCLK_MASK 0x00040000
55 #define IDLEST_MASK 0x00030000
56 #define MODULEMODE_MASK 0x00000003
57
58 #define GPIOX_GDBCLK_ENABLE 0x00040000
59 #define GPIOX_GDBCLK_DISABLE 0x00000000
60 #define IDLEST_FUNC 0x00000000
61 #define IDLEST_TRANS 0x00010000
62 #define IDLEST_IDLE 0x00020000
63 #define IDLEST_DISABLE 0x00030000
64
65 #define MODULEMODE_DISABLE 0x0
66 #define MODULEMODE_ENABLE 0x2
67
68 struct ti_clkctrl_clknode_sc {
69 device_t dev;
70 bool gdbclk;
71 /* omap4-cm range.host + ti,clkctrl reg[0] */
72 uint32_t register_offset;
73 };
74
75 #define WRITE4(_clk, off, val) \
76 CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
77 #define READ4(_clk, off, val) \
78 CLKDEV_READ_4(clknode_get_device(_clk), off, val)
79 #define DEVICE_LOCK(_clk) \
80 CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
81 #define DEVICE_UNLOCK(_clk) \
82 CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
83
84 static int
85 ti_clkctrl_init(struct clknode *clk, device_t dev)
86 {
87 struct ti_clkctrl_clknode_sc *sc;
88
89 sc = clknode_get_softc(clk);
90 sc->dev = dev;
91
92 clknode_init_parent_idx(clk, 0);
93 return (0);
94 }
95
96 static int
97 ti_clkctrl_set_gdbclk_gate(struct clknode *clk, bool enable)
98 {
99 struct ti_clkctrl_clknode_sc *sc;
100 uint32_t val, gpio_x_gdbclk;
101 uint32_t timeout = 100;
102
103 sc = clknode_get_softc(clk);
104
105 READ4(clk, sc->register_offset, &val);
106 DPRINTF(sc->dev, "val(%x) & (%x | %x = %x)\n",
107 val, GPIO_X_GDBCLK_MASK, MODULEMODE_MASK,
108 GPIO_X_GDBCLK_MASK | MODULEMODE_MASK);
109
110 if (enable) {
111 val = val & MODULEMODE_MASK;
112 val |= GPIOX_GDBCLK_ENABLE;
113 } else {
114 val = val & MODULEMODE_MASK;
115 val |= GPIOX_GDBCLK_DISABLE;
116 }
117
118 DPRINTF(sc->dev, "val %x\n", val);
119 WRITE4(clk, sc->register_offset, val);
120
121 /* Wait */
122 while (timeout) {
123 READ4(clk, sc->register_offset, &val);
124 gpio_x_gdbclk = val & GPIO_X_GDBCLK_MASK;
125 if (enable && (gpio_x_gdbclk == GPIOX_GDBCLK_ENABLE))
126 break;
127 else if (!enable && (gpio_x_gdbclk == GPIOX_GDBCLK_DISABLE))
128 break;
129 DELAY(10);
130 timeout--;
131 }
132 if (timeout == 0) {
133 device_printf(sc->dev, "ti_clkctrl_set_gdbclk_gate: Timeout\n");
134 return (1);
135 }
136
137 return (0);
138 }
139
140 static int
141 ti_clkctrl_set_gate(struct clknode *clk, bool enable)
142 {
143 struct ti_clkctrl_clknode_sc *sc;
144 uint32_t val, idlest, module;
145 uint32_t timeout=100;
146 int err;
147
148 sc = clknode_get_softc(clk);
149
150 if (sc->gdbclk) {
151 err = ti_clkctrl_set_gdbclk_gate(clk, enable);
152 return (err);
153 }
154
155 READ4(clk, sc->register_offset, &val);
156
157 if (enable)
158 WRITE4(clk, sc->register_offset, MODULEMODE_ENABLE);
159 else
160 WRITE4(clk, sc->register_offset, MODULEMODE_DISABLE);
161
162 while (timeout) {
163 READ4(clk, sc->register_offset, &val);
164 idlest = val & IDLEST_MASK;
165 module = val & MODULEMODE_MASK;
166 if (enable &&
167 (idlest == IDLEST_FUNC || idlest == IDLEST_TRANS) &&
168 module == MODULEMODE_ENABLE)
169 break;
170 else if (!enable &&
171 idlest == IDLEST_DISABLE &&
172 module == MODULEMODE_DISABLE)
173 break;
174 DELAY(10);
175 timeout--;
176 }
177
178 if (timeout == 0) {
179 device_printf(sc->dev, "ti_clkctrl_set_gate: Timeout\n");
180 return (1);
181 }
182
183 return (0);
184 }
185
186 static clknode_method_t ti_clkctrl_clknode_methods[] = {
187 /* Device interface */
188 CLKNODEMETHOD(clknode_init, ti_clkctrl_init),
189 CLKNODEMETHOD(clknode_set_gate, ti_clkctrl_set_gate),
190 CLKNODEMETHOD_END
191 };
192
193 DEFINE_CLASS_1(ti_clkctrl_clknode, ti_clkctrl_clknode_class,
194 ti_clkctrl_clknode_methods, sizeof(struct ti_clkctrl_clknode_sc),
195 clknode_class);
196
197 int
198 ti_clknode_clkctrl_register(struct clkdom *clkdom,
199 struct ti_clk_clkctrl_def *clkdef)
200 {
201 struct clknode *clk;
202 struct ti_clkctrl_clknode_sc *sc;
203
204 clk = clknode_create(clkdom, &ti_clkctrl_clknode_class,
205 &clkdef->clkdef);
206
207 if (clk == NULL) {
208 return (1);
209 }
210
211 sc = clknode_get_softc(clk);
212 sc->register_offset = clkdef->register_offset;
213 sc->gdbclk = clkdef->gdbclk;
214
215 if (clknode_register(clkdom, clk) == NULL) {
216 return (2);
217 }
218 return (0);
219 }
Cache object: 9d0a564711f3292dc67b0e3d4127f367
|