|
| 1 | +/* $NetBSD $ */ |
| 2 | + |
| 3 | +/*- |
| 4 | +* Copyright (c) 2025 The NetBSD Foundation, Inc. |
| 5 | +* All rights reserved. |
| 6 | +* |
| 7 | +* This code is derived from software contributed to The NetBSD Foundation |
| 8 | +* by Yuri Honegger. |
| 9 | +* |
| 10 | +* Redistribution and use in source and binary forms, with or without |
| 11 | +* modification, are permitted provided that the following conditions |
| 12 | +* are met: |
| 13 | +* 1. Redistributions of source code must retain the above copyright |
| 14 | +* notice, this list of conditions and the following disclaimer. |
| 15 | +* 2. Redistributions in binary form must reproduce the above copyright |
| 16 | +* notice, this list of conditions and the following disclaimer in the |
| 17 | +* documentation and/or other materials provided with the distribution. |
| 18 | +* |
| 19 | +* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
| 20 | +* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| 21 | +* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 22 | +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
| 23 | +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 24 | +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 25 | +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 26 | +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 27 | +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 28 | +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 29 | +* POSSIBILITY OF SUCH DAMAGE. |
| 30 | +*/ |
| 31 | + |
| 32 | +/* |
| 33 | + * Timer Interrupts for the TI AM18XX SOC |
| 34 | + */ |
| 35 | + |
| 36 | +#include <sys/param.h> |
| 37 | +#include <sys/cdefs.h> |
| 38 | +#include <sys/device.h> |
| 39 | + |
| 40 | +#include <dev/fdt/fdtvar.h> |
| 41 | + |
| 42 | +#include <arm/fdt/arm_fdtvar.h> |
| 43 | + |
| 44 | +struct am18_timer_softc { |
| 45 | + bus_space_tag_t sc_bst; |
| 46 | + bus_space_handle_t sc_bsh; |
| 47 | +}; |
| 48 | + |
| 49 | +static int am18_timer_match(device_t, cfdata_t, void *); |
| 50 | +static void am18_timer_attach(device_t, device_t, void *); |
| 51 | +static void am18_timer_cpu_initclocks(void); |
| 52 | +static int am18_timer_irq(void *); |
| 53 | + |
| 54 | +static struct am18_timer_softc *timer_sc; |
| 55 | + |
| 56 | +CFATTACH_DECL_NEW(am18timer, sizeof(struct am18_timer_softc), |
| 57 | + am18_timer_match, am18_timer_attach, NULL, NULL); |
| 58 | + |
| 59 | +#define AM18_TIMER_TIM12 0x10 |
| 60 | +#define AM18_TIMER_TIM34 0x14 |
| 61 | +#define AM18_TIMER_PRD12 0x18 |
| 62 | +#define AM18_TIMER_PRD34 0x1C |
| 63 | +#define AM18_TIMER_TCR 0x20 |
| 64 | +#define AM18_TIMER_TGCR 0x24 |
| 65 | + |
| 66 | +#define AM18_TIMER_TCR_ENAMODE12_CONTINUOUS 0x80 |
| 67 | +#define AM18_TIMER_TGCR_TIMMODE32_UNCHAINED 0x4 |
| 68 | +#define AM18_TIMER_TGCR_TIM12EN 0x1 |
| 69 | + |
| 70 | +#define TIMER_READ(sc, reg) \ |
| 71 | + bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, reg) |
| 72 | +#define TIMER_WRITE(sc, reg, val) \ |
| 73 | + bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, reg, val) |
| 74 | + |
| 75 | +static const struct device_compatible_entry compat_data[] = { |
| 76 | + { .compat = "ti,da830-timer" }, |
| 77 | + DEVICE_COMPAT_EOL |
| 78 | +}; |
| 79 | + |
| 80 | +static void |
| 81 | +am18_timer_cpu_initclocks(void) |
| 82 | +{ |
| 83 | + struct am18_timer_softc *sc = timer_sc; |
| 84 | + uint32_t timer_interval = 24000000/hz; |
| 85 | + |
| 86 | + /* disable counter to allow changing mode */ |
| 87 | + TIMER_WRITE(sc, AM18_TIMER_TCR, 0); |
| 88 | + /* set mode to 32-bit unchained */ |
| 89 | + TIMER_WRITE(sc, AM18_TIMER_TGCR, AM18_TIMER_TGCR_TIMMODE32_UNCHAINED | |
| 90 | + AM18_TIMER_TGCR_TIM12EN); |
| 91 | + /* start counting from zero */ |
| 92 | + TIMER_WRITE(sc, AM18_TIMER_TIM12, 0); |
| 93 | + TIMER_WRITE(sc, AM18_TIMER_TIM34, 0); |
| 94 | + /* load period registers with maximum period */ |
| 95 | + TIMER_WRITE(sc, AM18_TIMER_PRD12, timer_interval); |
| 96 | + TIMER_WRITE(sc, AM18_TIMER_PRD34, 0); |
| 97 | + /* enable timer */ |
| 98 | + TIMER_WRITE(sc, AM18_TIMER_TCR, AM18_TIMER_TCR_ENAMODE12_CONTINUOUS); |
| 99 | +} |
| 100 | + |
| 101 | +int |
| 102 | +am18_timer_irq(void *frame) |
| 103 | +{ |
| 104 | + hardclock(frame); |
| 105 | + |
| 106 | + return 1; |
| 107 | +} |
| 108 | + |
| 109 | +int |
| 110 | +am18_timer_match(device_t parent, cfdata_t cf, void *aux) |
| 111 | +{ |
| 112 | + struct fdt_attach_args * const faa = aux; |
| 113 | + |
| 114 | + return of_compatible_match(faa->faa_phandle, compat_data); |
| 115 | +} |
| 116 | + |
| 117 | +void |
| 118 | +am18_timer_attach(device_t parent, device_t self, void *aux) |
| 119 | +{ |
| 120 | + struct am18_timer_softc * const sc = device_private(self); |
| 121 | + struct fdt_attach_args * const faa = aux; |
| 122 | + const int phandle = faa->faa_phandle; |
| 123 | + bus_addr_t addr; |
| 124 | + bus_size_t size; |
| 125 | + char intrstr[128]; |
| 126 | + |
| 127 | + sc->sc_bst = faa->faa_bst; |
| 128 | + timer_sc = sc; |
| 129 | + |
| 130 | + if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { |
| 131 | + aprint_error(": couldn't get registers\n"); |
| 132 | + return; |
| 133 | + } |
| 134 | + if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { |
| 135 | + aprint_error(": couldn't map registers\n"); |
| 136 | + return; |
| 137 | + } |
| 138 | + |
| 139 | + /* establish interrupt */ |
| 140 | + if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { |
| 141 | + aprint_error(": failed to decode interrupt\n"); |
| 142 | + return; |
| 143 | + } |
| 144 | + void *ih = fdtbus_intr_establish_xname(phandle, 0, IPL_CLOCK, 0, |
| 145 | + am18_timer_irq, NULL, |
| 146 | + device_xname(self)); |
| 147 | + if (ih == NULL) { |
| 148 | + aprint_error_dev(self, "couldn't install timer interrupt\n"); |
| 149 | + return; |
| 150 | + } |
| 151 | + |
| 152 | + arm_fdt_timer_register(am18_timer_cpu_initclocks); |
| 153 | + |
| 154 | + aprint_normal(": timer on %s\n", intrstr); |
| 155 | +} |
| 156 | + |
0 commit comments