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