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