xref: /openbsd-src/sys/arch/armv7/exynos/exmct.c (revision 0f9e9ec23bb2b65cc62a3d17df12827a45dae80c)
1*0f9e9ec2Sjsg /* $OpenBSD: exmct.c,v 1.7 2024/05/13 01:15:50 jsg Exp $ */
207829fe8Sbmercer /*
307829fe8Sbmercer  * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
407829fe8Sbmercer  *
507829fe8Sbmercer  * Permission to use, copy, modify, and distribute this software for any
607829fe8Sbmercer  * purpose with or without fee is hereby granted, provided that the above
707829fe8Sbmercer  * copyright notice and this permission notice appear in all copies.
807829fe8Sbmercer  *
907829fe8Sbmercer  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1007829fe8Sbmercer  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1107829fe8Sbmercer  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1207829fe8Sbmercer  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1307829fe8Sbmercer  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1407829fe8Sbmercer  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1507829fe8Sbmercer  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1607829fe8Sbmercer  */
1707829fe8Sbmercer 
1807829fe8Sbmercer #include <sys/param.h>
1907829fe8Sbmercer #include <sys/systm.h>
2007829fe8Sbmercer #include <sys/device.h>
21fe1242bbSkettenis 
2207829fe8Sbmercer #include <arm/cpufunc.h>
23fe1242bbSkettenis 
2407829fe8Sbmercer #include <machine/intr.h>
2507829fe8Sbmercer #include <machine/bus.h>
2607829fe8Sbmercer #include <machine/fdt.h>
27fe1242bbSkettenis 
28fe1242bbSkettenis #include <dev/ofw/openfirm.h>
29fe1242bbSkettenis #include <dev/ofw/fdt.h>
3007829fe8Sbmercer 
3107829fe8Sbmercer /* registers */
3207829fe8Sbmercer #define MCT_CTRL	0x240
3307829fe8Sbmercer #define MCT_WRITE_STAT	0x24C
3407829fe8Sbmercer 
3507829fe8Sbmercer /* bits and bytes */
3607829fe8Sbmercer #define MCT_CTRL_START	(1 << 8)
3707829fe8Sbmercer 
3807829fe8Sbmercer struct exmct_softc {
3907829fe8Sbmercer 	struct device		sc_dev;
4007829fe8Sbmercer 	bus_space_tag_t		sc_iot;
4107829fe8Sbmercer 	bus_space_handle_t	sc_ioh;
4207829fe8Sbmercer };
4307829fe8Sbmercer 
4407829fe8Sbmercer struct exmct_softc *exmct_sc;
4507829fe8Sbmercer 
46fe1242bbSkettenis int exmct_match(struct device *, void *, void *);
47fe1242bbSkettenis void exmct_attach(struct device *, struct device *, void *);
4807829fe8Sbmercer 
499fdf0c62Smpi const struct cfattach	exmct_ca = {
5007829fe8Sbmercer 	sizeof (struct exmct_softc), exmct_match, exmct_attach
5107829fe8Sbmercer };
5207829fe8Sbmercer 
5307829fe8Sbmercer struct cfdriver exmct_cd = {
5407829fe8Sbmercer 	NULL, "exmct", DV_DULL
5507829fe8Sbmercer };
5607829fe8Sbmercer 
5707829fe8Sbmercer int
exmct_match(struct device * parent,void * match,void * aux)58fe1242bbSkettenis exmct_match(struct device *parent, void *match, void *aux)
5907829fe8Sbmercer {
60fe1242bbSkettenis 	struct fdt_attach_args *faa = aux;
6107829fe8Sbmercer 
62fe1242bbSkettenis 	return OF_is_compatible(faa->fa_node, "samsung,exynos4210-mct");
6307829fe8Sbmercer }
6407829fe8Sbmercer 
6507829fe8Sbmercer void
exmct_attach(struct device * parent,struct device * self,void * aux)66fe1242bbSkettenis exmct_attach(struct device *parent, struct device *self, void *aux)
6707829fe8Sbmercer {
6807829fe8Sbmercer 	struct exmct_softc *sc = (struct exmct_softc *)self;
69fe1242bbSkettenis 	struct fdt_attach_args *faa = aux;
7007829fe8Sbmercer 	uint32_t i, mask, reg;
7107829fe8Sbmercer 
72fe1242bbSkettenis 	sc->sc_iot = faa->fa_iot;
73fe1242bbSkettenis 
74fe1242bbSkettenis 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
75fe1242bbSkettenis 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
7607829fe8Sbmercer 		panic("%s: bus_space_map failed!", __func__);
7707829fe8Sbmercer 
7807829fe8Sbmercer 	printf("\n");
7907829fe8Sbmercer 
8007829fe8Sbmercer 	exmct_sc = sc;
8107829fe8Sbmercer 
82fe1242bbSkettenis 	extern void agtimer_delay(u_int);
83fe1242bbSkettenis 	arm_clock_register(NULL, agtimer_delay, NULL, NULL);
84fe1242bbSkettenis 
8507829fe8Sbmercer 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, MCT_CTRL,
8607829fe8Sbmercer 	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, MCT_CTRL) | MCT_CTRL_START);
8707829fe8Sbmercer 
8807829fe8Sbmercer 	mask = (1 << 16);
8907829fe8Sbmercer 
9007829fe8Sbmercer 	/* Wait 10 times until written value is applied */
9107829fe8Sbmercer 	for (i = 0; i < 10; i++) {
9207829fe8Sbmercer 		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MCT_WRITE_STAT);
9307829fe8Sbmercer 		if (reg & mask) {
9407829fe8Sbmercer 			bus_space_write_4(sc->sc_iot, sc->sc_ioh,
9507829fe8Sbmercer 			    MCT_WRITE_STAT, mask);
9607829fe8Sbmercer 			return;
9707829fe8Sbmercer 		}
9807829fe8Sbmercer 		cpufunc_nullop();
9907829fe8Sbmercer 	}
10007829fe8Sbmercer 
10107829fe8Sbmercer 	/* NOTREACHED */
10207829fe8Sbmercer 
103fe1242bbSkettenis 	panic("%s: can't enable timer!", __func__);
10407829fe8Sbmercer }
105