1*9fdf0c62Smpi /* $OpenBSD: amlreset.c,v 1.2 2021/10/24 17:52:26 mpi Exp $ */
24350d62eSkettenis /*
34350d62eSkettenis * Copyright (c) 2019 Mark Kettenis <kettenis@openbsd.org>
44350d62eSkettenis *
54350d62eSkettenis * Permission to use, copy, modify, and distribute this software for any
64350d62eSkettenis * purpose with or without fee is hereby granted, provided that the above
74350d62eSkettenis * copyright notice and this permission notice appear in all copies.
84350d62eSkettenis *
94350d62eSkettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
104350d62eSkettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
114350d62eSkettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
124350d62eSkettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
134350d62eSkettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
144350d62eSkettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
154350d62eSkettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
164350d62eSkettenis */
174350d62eSkettenis
184350d62eSkettenis #include <sys/param.h>
194350d62eSkettenis #include <sys/systm.h>
204350d62eSkettenis #include <sys/device.h>
214350d62eSkettenis
224350d62eSkettenis #include <machine/intr.h>
234350d62eSkettenis #include <machine/bus.h>
244350d62eSkettenis #include <machine/fdt.h>
254350d62eSkettenis
264350d62eSkettenis #include <dev/ofw/openfirm.h>
274350d62eSkettenis #include <dev/ofw/ofw_clock.h>
284350d62eSkettenis #include <dev/ofw/ofw_misc.h>
294350d62eSkettenis #include <dev/ofw/fdt.h>
304350d62eSkettenis
314350d62eSkettenis #define RESET0_REGISTER 0x0000
324350d62eSkettenis #define RESET0_MASK 0x003c
334350d62eSkettenis #define RESET0_LEVEL 0x007c
344350d62eSkettenis
354350d62eSkettenis #define HREAD4(sc, reg) \
364350d62eSkettenis (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
374350d62eSkettenis #define HWRITE4(sc, reg, val) \
384350d62eSkettenis bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
394350d62eSkettenis #define HSET4(sc, reg, bits) \
404350d62eSkettenis HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
414350d62eSkettenis #define HCLR4(sc, reg, bits) \
424350d62eSkettenis HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
434350d62eSkettenis
444350d62eSkettenis struct amlreset_softc {
454350d62eSkettenis struct device sc_dev;
464350d62eSkettenis bus_space_tag_t sc_iot;
474350d62eSkettenis bus_space_handle_t sc_ioh;
484350d62eSkettenis
494350d62eSkettenis struct reset_device sc_rd;
504350d62eSkettenis };
514350d62eSkettenis
524350d62eSkettenis int amlreset_match(struct device *, void *, void *);
534350d62eSkettenis void amlreset_attach(struct device *, struct device *, void *);
544350d62eSkettenis
55*9fdf0c62Smpi const struct cfattach amlreset_ca = {
564350d62eSkettenis sizeof (struct amlreset_softc), amlreset_match, amlreset_attach
574350d62eSkettenis };
584350d62eSkettenis
594350d62eSkettenis struct cfdriver amlreset_cd = {
604350d62eSkettenis NULL, "amlreset", DV_DULL
614350d62eSkettenis };
624350d62eSkettenis
634350d62eSkettenis void amlreset_reset(void *, uint32_t *, int);
644350d62eSkettenis
654350d62eSkettenis int
amlreset_match(struct device * parent,void * match,void * aux)664350d62eSkettenis amlreset_match(struct device *parent, void *match, void *aux)
674350d62eSkettenis {
684350d62eSkettenis struct fdt_attach_args *faa = aux;
694350d62eSkettenis
704350d62eSkettenis return OF_is_compatible(faa->fa_node, "amlogic,meson-axg-reset");
714350d62eSkettenis }
724350d62eSkettenis
734350d62eSkettenis void
amlreset_attach(struct device * parent,struct device * self,void * aux)744350d62eSkettenis amlreset_attach(struct device *parent, struct device *self, void *aux)
754350d62eSkettenis {
764350d62eSkettenis struct amlreset_softc *sc = (struct amlreset_softc *)self;
774350d62eSkettenis struct fdt_attach_args *faa = aux;
784350d62eSkettenis
794350d62eSkettenis if (faa->fa_nreg < 1) {
804350d62eSkettenis printf(": no registers\n");
814350d62eSkettenis return;
824350d62eSkettenis }
834350d62eSkettenis
844350d62eSkettenis sc->sc_iot = faa->fa_iot;
854350d62eSkettenis if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
864350d62eSkettenis faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
874350d62eSkettenis printf(": can't map registers\n");
884350d62eSkettenis return;
894350d62eSkettenis }
904350d62eSkettenis
914350d62eSkettenis printf("\n");
924350d62eSkettenis
934350d62eSkettenis sc->sc_rd.rd_node = faa->fa_node;
944350d62eSkettenis sc->sc_rd.rd_cookie = sc;
954350d62eSkettenis sc->sc_rd.rd_reset = amlreset_reset;
964350d62eSkettenis reset_register(&sc->sc_rd);
974350d62eSkettenis }
984350d62eSkettenis
994350d62eSkettenis void
amlreset_reset(void * cookie,uint32_t * cells,int assert)1004350d62eSkettenis amlreset_reset(void *cookie, uint32_t *cells, int assert)
1014350d62eSkettenis {
1024350d62eSkettenis struct amlreset_softc *sc = cookie;
1034350d62eSkettenis uint32_t bank = cells[0] / 32;
1044350d62eSkettenis uint32_t bit = cells[0] % 32;
1054350d62eSkettenis
1064350d62eSkettenis if (assert)
1074350d62eSkettenis HCLR4(sc, RESET0_LEVEL + bank * 4, (1 << bit));
1084350d62eSkettenis else
1094350d62eSkettenis HSET4(sc, RESET0_LEVEL + bank * 4, (1 << bit));
1104350d62eSkettenis }
111