xref: /openbsd-src/sys/dev/fdt/hiclock.c (revision c90a81c56dcebd6a1b73fe4aff9b03385b8e63b3)
1 /*	$OpenBSD: hiclock.c,v 1.1 2018/08/27 20:05:06 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 
22 #include <machine/intr.h>
23 #include <machine/bus.h>
24 #include <machine/fdt.h>
25 
26 #include <dev/ofw/openfirm.h>
27 #include <dev/ofw/ofw_clock.h>
28 #include <dev/ofw/ofw_misc.h>
29 #include <dev/ofw/fdt.h>
30 
31 #define HREAD4(sc, reg)							\
32 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
33 #define HWRITE4(sc, reg, val)						\
34 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
35 
36 /*
37  * This driver is based on preliminary device tree bindings and will
38  * almost certainly need changes once the official bindings land in
39  * mainline Linux.  Support for these preliminary bindings will be
40  * dropped as soon as official bindings are available.
41  */
42 
43 struct hiclock_softc {
44 	struct device		sc_dev;
45 	bus_space_tag_t		sc_iot;
46 	bus_space_handle_t	sc_ioh;
47 
48 	struct clock_device	sc_cd;
49 };
50 
51 int hiclock_match(struct device *, void *, void *);
52 void hiclock_attach(struct device *, struct device *, void *);
53 
54 struct cfattach	hiclock_ca = {
55 	sizeof (struct hiclock_softc), hiclock_match, hiclock_attach
56 };
57 
58 struct cfdriver hiclock_cd = {
59 	NULL, "hiclock", DV_DULL
60 };
61 
62 uint32_t kirin970_crgctrl_get_frequency(void *, uint32_t *);
63 void	kirin970_crgctrl_enable(void *, uint32_t *, int);
64 uint32_t hiclock_get_frequency(void *, uint32_t *);
65 void	hiclock_enable(void *, uint32_t *, int);
66 
67 int
68 hiclock_match(struct device *parent, void *match, void *aux)
69 {
70 	struct fdt_attach_args *faa = aux;
71 
72 	if (OF_is_compatible(faa->fa_node, "hisilicon,kirin970-crgctrl") ||
73 	    OF_is_compatible(faa->fa_node, "hisilicon,kirin970-pctrl") ||
74 	    OF_is_compatible(faa->fa_node, "hisilicon,kirin970-pmuctrl") ||
75 	    OF_is_compatible(faa->fa_node, "hisilicon,kirin970-pmctrl") ||
76 	    OF_is_compatible(faa->fa_node, "hisilicon,kirin970-sctrl") ||
77 	    OF_is_compatible(faa->fa_node, "hisilicon,kirin970-iomcu") ||
78 	    OF_is_compatible(faa->fa_node, "hisilicon,media1-crg") ||
79 	    OF_is_compatible(faa->fa_node, "hisilicon,media2-crg"))
80 		return 10;	/* Must beat syscon(4). */
81 
82 	return 0;
83 }
84 
85 void
86 hiclock_attach(struct device *parent, struct device *self, void *aux)
87 {
88 	struct hiclock_softc *sc = (struct hiclock_softc *)self;
89 	struct fdt_attach_args *faa = aux;
90 
91 	if (faa->fa_nreg < 1) {
92 		printf(": no registers\n");
93 		return;
94 	}
95 
96 	sc->sc_iot = faa->fa_iot;
97 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
98 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
99 		printf(": can't map registers\n");
100 		return;
101 	}
102 
103 	if (OF_is_compatible(faa->fa_node, "syscon")) {
104 		regmap_register(faa->fa_node, sc->sc_iot, sc->sc_ioh,
105 		    faa->fa_reg[0].size);
106 	}
107 
108 	printf("\n");
109 
110 	sc->sc_cd.cd_node = faa->fa_node;
111 	sc->sc_cd.cd_cookie = sc;
112 	if (OF_is_compatible(faa->fa_node, "hisilicon,kirin970-crgctrl")) {
113 	    sc->sc_cd.cd_get_frequency = kirin970_crgctrl_get_frequency;
114 	    sc->sc_cd.cd_enable = kirin970_crgctrl_enable;
115 	} else {
116 	    sc->sc_cd.cd_get_frequency = hiclock_get_frequency;
117 	    sc->sc_cd.cd_enable = hiclock_enable;
118 	}
119 	clock_register(&sc->sc_cd);
120 }
121 
122 #define KIRIN970_CLKIN_SYS		0
123 #define KIRIN970_CLK_PPLL0		3
124 #define KIRIN970_CLK_PPLL2		5
125 #define KIRIN970_CLK_PPLL3		6
126 
127 #define KIRIN970_CLK_SD_SYS		22
128 #define KIRIN970_CLK_SDIO_SYS		23
129 #define KIRIN970_CLK_GATE_ABB_USB	29
130 #define KIRIN970_CLK_MUX_SD_SYS		68
131 #define KIRIN970_CLK_MUX_SD_PLL 	69
132 #define KIRIN970_CLK_MUX_SDIO_SYS	70
133 #define KIRIN970_CLK_MUX_SDIO_PLL 	71
134 #define KIRIN970_CLK_DIV_SD		93
135 #define KIRIN970_CLK_DIV_SDIO		94
136 #define KIRIN970_HCLK_GATE_USB3OTG	147
137 #define KIRIN970_HCLK_GATE_USB3DVFS	148
138 #define KIRIN970_HCLK_GATE_SDIO		149
139 #define KIRIN970_CLK_GATE_SD		159
140 #define KIRIN970_HCLK_GATE_SD		160
141 #define KIRIN970_CLK_GATE_SDIO		161
142 #define KIRIN970_CLK_GATE_USB3OTG_REF	189
143 
144 uint32_t
145 kirin970_crgctrl_get_frequency(void *cookie, uint32_t *cells)
146 {
147 	struct hiclock_softc *sc = cookie;
148 	uint32_t idx = cells[0];
149 	uint32_t reg, freq, div;
150 	int mux;
151 
152 	switch (idx) {
153 	case KIRIN970_CLKIN_SYS:
154 		return 19200000;
155 	case KIRIN970_CLK_PPLL0:
156 		return 1660000000;
157 	case KIRIN970_CLK_PPLL2:
158 		return 1920000000;
159 	case KIRIN970_CLK_PPLL3:
160 		return 1200000000;
161 	case KIRIN970_CLK_SD_SYS:
162 	case KIRIN970_CLK_SDIO_SYS:
163 		idx = KIRIN970_CLKIN_SYS;
164 		freq = kirin970_crgctrl_get_frequency(cookie, &idx);
165 		return freq / 6;
166 	case KIRIN970_CLK_MUX_SD_SYS:
167 		reg = HREAD4(sc, 0x0b8);
168 		mux = (reg >> 6) & 0x1;
169 		idx = mux ? KIRIN970_CLK_DIV_SD : KIRIN970_CLK_SD_SYS;
170 		return kirin970_crgctrl_get_frequency(cookie, &idx);
171 	case KIRIN970_CLK_MUX_SD_PLL:
172 		reg = HREAD4(sc, 0x0b8);
173 		mux = (reg >> 4) & 0x3;
174 		switch (mux) {
175 		case 0:
176 			idx = KIRIN970_CLK_PPLL0;
177 			break;
178 		case 1:
179 			idx = KIRIN970_CLK_PPLL3;
180 			break;
181 		case 2:
182 		case 3:
183 			idx = KIRIN970_CLK_PPLL2;
184 			break;
185 		}
186 		return kirin970_crgctrl_get_frequency(cookie, &idx);
187 	case KIRIN970_CLK_DIV_SD:
188 		reg = HREAD4(sc, 0x0b8);
189 		div = (reg >> 0) & 0xf;
190 		idx = KIRIN970_CLK_MUX_SD_PLL;
191 		freq = kirin970_crgctrl_get_frequency(cookie, &idx);
192 		return freq / (div + 1);
193 	case KIRIN970_CLK_GATE_SD:
194 		idx = KIRIN970_CLK_MUX_SD_SYS;
195 		return kirin970_crgctrl_get_frequency(cookie, &idx);
196 	case KIRIN970_CLK_GATE_SDIO:
197 		idx = KIRIN970_CLK_MUX_SDIO_SYS;
198 		return kirin970_crgctrl_get_frequency(cookie, &idx);
199 	}
200 
201 	printf("%s: 0x%08x\n", __func__, idx);
202 	return 0;
203 }
204 
205 void
206 kirin970_crgctrl_enable(void *cookie, uint32_t *cells, int on)
207 {
208 	uint32_t idx = cells[0];
209 
210 	switch (idx) {
211 	case KIRIN970_CLK_GATE_ABB_USB:
212 	case KIRIN970_HCLK_GATE_USB3OTG:
213 	case KIRIN970_HCLK_GATE_USB3DVFS:
214 	case KIRIN970_CLK_GATE_SD:
215 	case KIRIN970_HCLK_GATE_SD:
216 	case KIRIN970_CLK_GATE_USB3OTG_REF:
217 		/* Enabled by default. */
218 		return;
219 	}
220 
221 	printf("%s: 0x%08x\n", __func__, idx);
222 }
223 
224 uint32_t
225 hiclock_get_frequency(void *cookie, uint32_t *cells)
226 {
227 	uint32_t idx = cells[0];
228 
229 	printf("%s: 0x%08x\n", __func__, idx);
230 	return 0;
231 }
232 
233 void
234 hiclock_enable(void *cookie, uint32_t *cells, int on)
235 {
236 	uint32_t idx = cells[0];
237 
238 	printf("%s: 0x%08x\n", __func__, idx);
239 }
240