xref: /netbsd-src/sys/arch/arm/imx/imxsnvs.c (revision 90313c06e62e910bf0d1bb24faa9d17dcefd0ab6)
1*90313c06Smsaitoh /*	$NetBSD: imxsnvs.c,v 1.2 2024/02/07 04:20:26 msaitoh Exp $	*/
2ec482321Sryo 
3ec482321Sryo /*
4*90313c06Smsaitoh  * Copyright (c) 2014 Ryo Shimizu
5ec482321Sryo  * All rights reserved.
6ec482321Sryo  *
7ec482321Sryo  * Redistribution and use in source and binary forms, with or without
8ec482321Sryo  * modification, are permitted provided that the following conditions
9ec482321Sryo  * are met:
10ec482321Sryo  * 1. Redistributions of source code must retain the above copyright
11ec482321Sryo  *    notice, this list of conditions and the following disclaimer.
12ec482321Sryo  * 2. Redistributions in binary form must reproduce the above copyright
13ec482321Sryo  *    notice, this list of conditions and the following disclaimer in the
14ec482321Sryo  *    documentation and/or other materials provided with the distribution.
15ec482321Sryo  *
16ec482321Sryo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17ec482321Sryo  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18ec482321Sryo  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19ec482321Sryo  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20ec482321Sryo  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21ec482321Sryo  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22ec482321Sryo  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23ec482321Sryo  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24ec482321Sryo  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25ec482321Sryo  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26ec482321Sryo  * POSSIBILITY OF SUCH DAMAGE.
27ec482321Sryo  */
28ec482321Sryo 
29ec482321Sryo /*
30ec482321Sryo  * i.MX6,7 Secure Non-Volatile Storage
31ec482321Sryo  */
32ec482321Sryo #include <sys/cdefs.h>
33*90313c06Smsaitoh __KERNEL_RCSID(0, "$NetBSD: imxsnvs.c,v 1.2 2024/02/07 04:20:26 msaitoh Exp $");
34ec482321Sryo 
35ec482321Sryo #include "locators.h"
36ec482321Sryo #include <sys/bus.h>
37ec482321Sryo #include <sys/device.h>
38ec482321Sryo #include <sys/param.h>
39ec482321Sryo #include <dev/clock_subr.h>
40ec482321Sryo 
41ec482321Sryo #include <arm/imx/imxsnvsreg.h>
42ec482321Sryo #include <arm/imx/imxsnvsvar.h>
43ec482321Sryo 
44ec482321Sryo struct imxsnvs_softc {
45ec482321Sryo 	device_t sc_dev;
46ec482321Sryo 	bus_space_tag_t sc_iot;
47ec482321Sryo 	bus_space_handle_t sc_ioh;
48ec482321Sryo 	struct todr_chip_handle sc_todr;
49ec482321Sryo };
50ec482321Sryo 
51ec482321Sryo #define SNVS_READ(sc, reg)					\
52ec482321Sryo 	bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, reg)
53ec482321Sryo 
54ec482321Sryo #define SNVS_WRITE(sc, reg, val)				\
55ec482321Sryo 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, reg, val)
56ec482321Sryo 
57ec482321Sryo static int imxsnvs_rtc_enable(struct imxsnvs_softc *);
58ec482321Sryo static int imxsnvs_rtc_disable(struct imxsnvs_softc *);
59ec482321Sryo static int imxsnvs_gettime(todr_chip_handle_t, struct timeval *);
60ec482321Sryo static int imxsnvs_settime(todr_chip_handle_t, struct timeval *);
61ec482321Sryo 
62ec482321Sryo 
63ec482321Sryo CFATTACH_DECL_NEW(imxsnvs, sizeof(struct imxsnvs_softc),
64ec482321Sryo     imxsnvs_match, imxsnvs_attach, NULL, NULL);
65ec482321Sryo 
66ec482321Sryo /* ARGSUSED */
67ec482321Sryo int
imxsnvs_attach_common(device_t parent __unused,device_t self,bus_space_tag_t iot,paddr_t iobase,size_t size,int intr __unused,int flags __unused)68ec482321Sryo imxsnvs_attach_common(device_t parent __unused, device_t self,
69ec482321Sryo                       bus_space_tag_t iot, paddr_t iobase, size_t size,
70ec482321Sryo                       int intr __unused, int flags __unused)
71ec482321Sryo {
72ec482321Sryo 	struct imxsnvs_softc *sc;
73ec482321Sryo 	uint32_t v1, v2;
74ec482321Sryo 
75ec482321Sryo 	sc = device_private(self);
76ec482321Sryo 	sc->sc_dev = self;
77ec482321Sryo 	sc->sc_iot = iot;
78ec482321Sryo 
79ec482321Sryo 	aprint_naive("\n");
80ec482321Sryo 	aprint_normal(": Secure Non-Volatile Storage\n");
81ec482321Sryo 	if (bus_space_map(sc->sc_iot, iobase, size, 0,
82ec482321Sryo 	    &sc->sc_ioh)) {
83ec482321Sryo 		aprint_error_dev(self, "Cannot map registers\n");
84ec482321Sryo 		return 1;
85ec482321Sryo 	}
86ec482321Sryo 
87ec482321Sryo 	v1 = SNVS_READ(sc, SNVS_HPVIDR1);
88ec482321Sryo 	v2 = SNVS_READ(sc, SNVS_HPVIDR2);
89ec482321Sryo 	aprint_verbose_dev(self, "id=0x%llx, ver=%lld.%lld, ip_era=0x%llx, "
90ec482321Sryo 	    "intg_opt=0x%llx, eco_rev=0x%llx, config_opt=0x%llx\n",
91ec482321Sryo 	    __SHIFTOUT(v1, SNVS_HPVIDR1_IP_ID),
92ec482321Sryo 	    __SHIFTOUT(v1, SNVS_HPVIDR1_MAJOR_REV),
93ec482321Sryo 	    __SHIFTOUT(v1, SNVS_HPVIDR1_MINOR_REV),
94ec482321Sryo 	    __SHIFTOUT(v2, SNVS_HPVIDR2_IP_ERA),
95ec482321Sryo 	    __SHIFTOUT(v2, SNVS_HPVIDR2_INTG_OPT),
96ec482321Sryo 	    __SHIFTOUT(v2, SNVS_HPVIDR2_ECO_REV),
97ec482321Sryo 	    __SHIFTOUT(v2, SNVS_HPVIDR2_CONFIG_OPT));
98ec482321Sryo 
99ec482321Sryo 	if (imxsnvs_rtc_enable(sc) != 0) {
100ec482321Sryo 		aprint_error_dev(self, "cannot enable RTC\n");
101ec482321Sryo 		return 1;
102ec482321Sryo 	}
103ec482321Sryo 
104ec482321Sryo 	sc->sc_todr.todr_gettime = imxsnvs_gettime;
105ec482321Sryo 	sc->sc_todr.todr_settime = imxsnvs_settime;
106ec482321Sryo 	sc->sc_todr.cookie = sc;
107ec482321Sryo 	todr_attach(&sc->sc_todr);
108ec482321Sryo 
109ec482321Sryo 	return 0;
110ec482321Sryo }
111ec482321Sryo 
112ec482321Sryo static int
imxsnvs_rtc_enable(struct imxsnvs_softc * sc)113ec482321Sryo imxsnvs_rtc_enable(struct imxsnvs_softc *sc)
114ec482321Sryo {
115ec482321Sryo 	uint32_t v;
116ec482321Sryo 	int timeout;
117ec482321Sryo 
118ec482321Sryo 	/* enable SRTC */
119ec482321Sryo 	v = SNVS_READ(sc, SNVS_LPCR);
120ec482321Sryo 	SNVS_WRITE(sc, SNVS_LPCR, v | SNVS_LPCR_SRTC_ENV);
121ec482321Sryo 	for (timeout = 10000; timeout > 0; timeout--) {
122ec482321Sryo 		if (SNVS_READ(sc, SNVS_LPCR) & SNVS_LPCR_SRTC_ENV)
123ec482321Sryo 			break;
124ec482321Sryo 	}
125ec482321Sryo 	if (timeout == 0)
126ec482321Sryo 		return ETIMEDOUT;
127ec482321Sryo 
128ec482321Sryo 	return 0;
129ec482321Sryo }
130ec482321Sryo 
131ec482321Sryo static int
imxsnvs_rtc_disable(struct imxsnvs_softc * sc)132ec482321Sryo imxsnvs_rtc_disable(struct imxsnvs_softc *sc)
133ec482321Sryo {
134ec482321Sryo 	uint32_t v;
135ec482321Sryo 	int timeout;
136ec482321Sryo 
137ec482321Sryo 	/* disable SRTC */
138ec482321Sryo 	v = SNVS_READ(sc, SNVS_LPCR);
139ec482321Sryo 	SNVS_WRITE(sc, SNVS_LPCR, v & ~SNVS_LPCR_SRTC_ENV);
140ec482321Sryo 	for (timeout = 10000; timeout > 0; timeout--) {
141ec482321Sryo 		if (!(SNVS_READ(sc, SNVS_LPCR) & SNVS_LPCR_SRTC_ENV))
142ec482321Sryo 			break;
143ec482321Sryo 	}
144ec482321Sryo 	if (timeout == 0)
145ec482321Sryo 		return ETIMEDOUT;
146ec482321Sryo 
147ec482321Sryo 	return 0;
148ec482321Sryo }
149ec482321Sryo 
150ec482321Sryo static int
imxsnvs_gettime(todr_chip_handle_t tch,struct timeval * tvp)151ec482321Sryo imxsnvs_gettime(todr_chip_handle_t tch, struct timeval *tvp)
152ec482321Sryo {
153ec482321Sryo 	struct imxsnvs_softc *sc;
154ec482321Sryo 	uint64_t c1, c2;
155ec482321Sryo 
156ec482321Sryo 	sc = tch->cookie;
157ec482321Sryo 
158ec482321Sryo 	c2 = ((uint64_t)SNVS_READ(sc, SNVS_LPSRTCMR) << 32) +
159ec482321Sryo 	    SNVS_READ(sc, SNVS_LPSRTCLR);
160ec482321Sryo 	do {
161ec482321Sryo 		c1 = c2;
162ec482321Sryo 		c2 = ((uint64_t)SNVS_READ(sc, SNVS_LPSRTCMR) << 32) +
163ec482321Sryo 		    SNVS_READ(sc, SNVS_LPSRTCLR);
164ec482321Sryo 	} while (c1 != c2);
165ec482321Sryo 
166ec482321Sryo 	tvp->tv_sec = c1 >> SVNS_COUNTER_SHIFT;
167ec482321Sryo 	tvp->tv_usec = (c1 % SVNS_COUNTER_HZ) * 1000000 / SVNS_COUNTER_HZ;
168ec482321Sryo 
169ec482321Sryo 	return 0;
170ec482321Sryo }
171ec482321Sryo 
172ec482321Sryo static int
imxsnvs_settime(todr_chip_handle_t tch,struct timeval * tvp)173ec482321Sryo imxsnvs_settime(todr_chip_handle_t tch, struct timeval *tvp)
174ec482321Sryo {
175ec482321Sryo 	struct imxsnvs_softc *sc;
176ec482321Sryo 	uint64_t c, h, l;
177ec482321Sryo 	int rv;
178ec482321Sryo 
179ec482321Sryo 	c = (uint64_t)tvp->tv_sec * SVNS_COUNTER_HZ +
180ec482321Sryo 	    (uint64_t)tvp->tv_usec * SVNS_COUNTER_HZ / 1000000;
181ec482321Sryo 	h = __SHIFTIN((c >> 32) & SNVS_LPSRTCMR_SRTC, SNVS_LPSRTCMR_SRTC);
182ec482321Sryo 	l = c & 0xffffffff;
183ec482321Sryo 
184ec482321Sryo 	sc = tch->cookie;
185ec482321Sryo 	if ((rv = imxsnvs_rtc_disable(sc)) != 0)
186ec482321Sryo 		return rv;
187ec482321Sryo 
188ec482321Sryo 	SNVS_WRITE(sc, SNVS_LPSRTCMR, h);
189ec482321Sryo 	SNVS_WRITE(sc, SNVS_LPSRTCLR, l);
190ec482321Sryo 
191ec482321Sryo 	if ((rv = imxsnvs_rtc_enable(sc)) != 0)
192ec482321Sryo 		return rv;
193ec482321Sryo 
194ec482321Sryo 	return 0;
195ec482321Sryo }
196