1 /* $OpenBSD: exmct.c,v 1.4 2016/07/26 22:10:10 patrick Exp $ */ 2 /* 3 * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/queue.h> 21 #include <sys/malloc.h> 22 #include <sys/device.h> 23 #include <sys/evcount.h> 24 #include <sys/socket.h> 25 #include <sys/timeout.h> 26 #include <arm/cpufunc.h> 27 #include <machine/intr.h> 28 #include <machine/bus.h> 29 #if NFDT > 0 30 #include <machine/fdt.h> 31 #endif 32 #include <armv7/armv7/armv7var.h> 33 34 /* registers */ 35 #define MCT_CTRL 0x240 36 #define MCT_WRITE_STAT 0x24C 37 38 /* bits and bytes */ 39 #define MCT_CTRL_START (1 << 8) 40 41 struct exmct_softc { 42 struct device sc_dev; 43 bus_space_tag_t sc_iot; 44 bus_space_handle_t sc_ioh; 45 }; 46 47 struct exmct_softc *exmct_sc; 48 49 int exmct_match(struct device *parent, void *v, void *aux); 50 void exmct_attach(struct device *parent, struct device *self, void *args); 51 void exmct_stop(void); 52 void exmct_reset(void); 53 54 struct cfattach exmct_ca = { 55 sizeof (struct exmct_softc), NULL, exmct_attach 56 }; 57 struct cfattach exmct_fdt_ca = { 58 sizeof (struct exmct_softc), exmct_match, exmct_attach 59 }; 60 61 struct cfdriver exmct_cd = { 62 NULL, "exmct", DV_DULL 63 }; 64 65 int 66 exmct_match(struct device *parent, void *v, void *aux) 67 { 68 #if NFDT > 0 69 struct armv7_attach_args *aa = aux; 70 71 if (fdt_node_compatible("samsung,exynos4210-mct", aa->aa_node)) 72 return 1; 73 #endif 74 75 return 0; 76 } 77 78 void 79 exmct_attach(struct device *parent, struct device *self, void *args) 80 { 81 struct armv7_attach_args *aa = args; 82 struct exmct_softc *sc = (struct exmct_softc *) self; 83 struct armv7mem mem; 84 uint32_t i, mask, reg; 85 86 sc->sc_iot = aa->aa_iot; 87 #if NFDT > 0 88 if (aa->aa_node) { 89 struct fdt_reg reg; 90 if (fdt_get_reg(aa->aa_node, 0, ®)) 91 panic("%s: could not extract memory data from FDT", 92 __func__); 93 mem.addr = reg.addr; 94 mem.size = reg.size; 95 } else 96 #endif 97 { 98 mem.addr = aa->aa_dev->mem[0].addr; 99 mem.size = aa->aa_dev->mem[0].size; 100 } 101 if (bus_space_map(sc->sc_iot, mem.addr, mem.size, 0, &sc->sc_ioh)) 102 panic("%s: bus_space_map failed!", __func__); 103 104 printf("\n"); 105 106 exmct_sc = sc; 107 108 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MCT_CTRL, 109 bus_space_read_4(sc->sc_iot, sc->sc_ioh, MCT_CTRL) | MCT_CTRL_START); 110 111 mask = (1 << 16); 112 113 /* Wait 10 times until written value is applied */ 114 for (i = 0; i < 10; i++) { 115 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MCT_WRITE_STAT); 116 if (reg & mask) { 117 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 118 MCT_WRITE_STAT, mask); 119 return; 120 } 121 cpufunc_nullop(); 122 } 123 124 /* NOTREACHED */ 125 126 panic("%s: Can't enable timer!", __func__); 127 } 128