xref: /netbsd-src/sys/arch/arm/amlogic/meson_rng.c (revision 084d57f7d65e8c6f49bc2edae84881a7bed2319c)
1*084d57f7Sriastradh /* $NetBSD: meson_rng.c,v 1.5 2022/03/19 11:36:43 riastradh Exp $ */
2912cfa14Sjmcneill 
3912cfa14Sjmcneill /*-
4912cfa14Sjmcneill  * Copyright (c) 2015-2019 Jared D. McNeill <jmcneill@invisible.ca>
5912cfa14Sjmcneill  * All rights reserved.
6912cfa14Sjmcneill  *
7912cfa14Sjmcneill  * Redistribution and use in source and binary forms, with or without
8912cfa14Sjmcneill  * modification, are permitted provided that the following conditions
9912cfa14Sjmcneill  * are met:
10912cfa14Sjmcneill  * 1. Redistributions of source code must retain the above copyright
11912cfa14Sjmcneill  *    notice, this list of conditions and the following disclaimer.
12912cfa14Sjmcneill  * 2. Redistributions in binary form must reproduce the above copyright
13912cfa14Sjmcneill  *    notice, this list of conditions and the following disclaimer in the
14912cfa14Sjmcneill  *    documentation and/or other materials provided with the distribution.
15912cfa14Sjmcneill  *
16912cfa14Sjmcneill  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17912cfa14Sjmcneill  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18912cfa14Sjmcneill  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19912cfa14Sjmcneill  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20912cfa14Sjmcneill  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21912cfa14Sjmcneill  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22912cfa14Sjmcneill  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23912cfa14Sjmcneill  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24912cfa14Sjmcneill  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25912cfa14Sjmcneill  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26912cfa14Sjmcneill  * SUCH DAMAGE.
27912cfa14Sjmcneill  */
28912cfa14Sjmcneill 
29912cfa14Sjmcneill #include <sys/cdefs.h>
30*084d57f7Sriastradh __KERNEL_RCSID(0, "$NetBSD: meson_rng.c,v 1.5 2022/03/19 11:36:43 riastradh Exp $");
31912cfa14Sjmcneill 
32912cfa14Sjmcneill #include <sys/param.h>
33912cfa14Sjmcneill #include <sys/bus.h>
34912cfa14Sjmcneill #include <sys/device.h>
35912cfa14Sjmcneill #include <sys/systm.h>
36912cfa14Sjmcneill #include <sys/kernel.h>
37912cfa14Sjmcneill #include <sys/mutex.h>
38912cfa14Sjmcneill #include <sys/rndsource.h>
39912cfa14Sjmcneill 
40912cfa14Sjmcneill #include <dev/fdt/fdtvar.h>
41912cfa14Sjmcneill 
42912cfa14Sjmcneill static int	meson_rng_match(device_t, cfdata_t, void *);
43912cfa14Sjmcneill static void	meson_rng_attach(device_t, device_t, void *);
44912cfa14Sjmcneill 
45912cfa14Sjmcneill static void	meson_rng_get(size_t, void *);
46912cfa14Sjmcneill 
47912cfa14Sjmcneill struct meson_rng_softc {
48912cfa14Sjmcneill 	device_t		sc_dev;
49912cfa14Sjmcneill 	bus_space_tag_t		sc_bst;
50912cfa14Sjmcneill 	bus_space_handle_t	sc_bsh;
51912cfa14Sjmcneill 
52912cfa14Sjmcneill 	krndsource_t		sc_rndsource;
53912cfa14Sjmcneill };
54912cfa14Sjmcneill 
556e54367aSthorpej static const struct device_compatible_entry compat_data[] = {
566e54367aSthorpej 	{ .compat = "amlogic,meson-rng" },
576e54367aSthorpej 	DEVICE_COMPAT_EOL
58912cfa14Sjmcneill };
59912cfa14Sjmcneill 
60912cfa14Sjmcneill CFATTACH_DECL_NEW(meson_rng, sizeof(struct meson_rng_softc),
61912cfa14Sjmcneill 	meson_rng_match, meson_rng_attach, NULL, NULL);
62912cfa14Sjmcneill 
63912cfa14Sjmcneill static int
meson_rng_match(device_t parent,cfdata_t cf,void * aux)64912cfa14Sjmcneill meson_rng_match(device_t parent, cfdata_t cf, void *aux)
65912cfa14Sjmcneill {
66912cfa14Sjmcneill 	struct fdt_attach_args * const faa = aux;
67912cfa14Sjmcneill 
686e54367aSthorpej 	return of_compatible_match(faa->faa_phandle, compat_data);
69912cfa14Sjmcneill }
70912cfa14Sjmcneill 
71912cfa14Sjmcneill static void
meson_rng_attach(device_t parent,device_t self,void * aux)72912cfa14Sjmcneill meson_rng_attach(device_t parent, device_t self, void *aux)
73912cfa14Sjmcneill {
74912cfa14Sjmcneill 	struct meson_rng_softc * const sc = device_private(self);
75912cfa14Sjmcneill 	struct fdt_attach_args * const faa = aux;
76912cfa14Sjmcneill 	const int phandle = faa->faa_phandle;
77912cfa14Sjmcneill 	struct clk *clk;
78912cfa14Sjmcneill 	bus_addr_t addr;
79912cfa14Sjmcneill 	bus_size_t size;
80912cfa14Sjmcneill 
81912cfa14Sjmcneill 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
82912cfa14Sjmcneill 		aprint_error(": couldn't get registers\n");
83912cfa14Sjmcneill 		return;
84912cfa14Sjmcneill 	}
85912cfa14Sjmcneill 
86912cfa14Sjmcneill 	sc->sc_dev = self;
87912cfa14Sjmcneill 	sc->sc_bst = faa->faa_bst;
88912cfa14Sjmcneill 	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
89912cfa14Sjmcneill 		aprint_error(": couldn't map registers\n");
90912cfa14Sjmcneill 		return;
91912cfa14Sjmcneill 	}
92912cfa14Sjmcneill 
93813b0337Sjmcneill 	/* Core clock is optional */
94912cfa14Sjmcneill 	clk = fdtbus_clock_get(phandle, "core");
95813b0337Sjmcneill 	if (clk != NULL && clk_enable(clk) != 0) {
96912cfa14Sjmcneill 		aprint_error(": couldn't enable core clock\n");
97912cfa14Sjmcneill 		return;
98912cfa14Sjmcneill 	}
99912cfa14Sjmcneill 
100912cfa14Sjmcneill 	aprint_naive("\n");
101912cfa14Sjmcneill 	aprint_normal(": Hardware RNG\n");
102912cfa14Sjmcneill 
103912cfa14Sjmcneill 	rndsource_setcb(&sc->sc_rndsource, meson_rng_get, sc);
104912cfa14Sjmcneill 	rnd_attach_source(&sc->sc_rndsource, device_xname(self), RND_TYPE_RNG,
105912cfa14Sjmcneill 	    RND_FLAG_COLLECT_VALUE|RND_FLAG_HASCB);
106912cfa14Sjmcneill }
107912cfa14Sjmcneill 
108912cfa14Sjmcneill static void
meson_rng_get(size_t bytes_wanted,void * priv)109912cfa14Sjmcneill meson_rng_get(size_t bytes_wanted, void *priv)
110912cfa14Sjmcneill {
111912cfa14Sjmcneill 	struct meson_rng_softc * const sc = priv;
112813b0337Sjmcneill 	uint32_t data;
113912cfa14Sjmcneill 
114912cfa14Sjmcneill 	while (bytes_wanted) {
115813b0337Sjmcneill 		data = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 0);
116813b0337Sjmcneill 		rnd_add_data_sync(&sc->sc_rndsource, &data, sizeof(data),
117912cfa14Sjmcneill 		    sizeof(data) * NBBY);
118912cfa14Sjmcneill 		bytes_wanted -= MIN(bytes_wanted, sizeof(data));
119912cfa14Sjmcneill 	}
120813b0337Sjmcneill 	explicit_memset(&data, 0, sizeof(data));
121912cfa14Sjmcneill }
122