Module Name: src Committed By: jmcneill Date: Mon Jul 2 12:49:37 UTC 2018
Modified Files: src/sys/arch/arm/samsung: exynos_platform.c mct.c mct_var.h Log Message: Add a proper MCT driver rather than relying on ARM Generic Timer (which may not be functional or even present). To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/arch/arm/samsung/exynos_platform.c cvs rdiff -u -r1.13 -r1.14 src/sys/arch/arm/samsung/mct.c cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/samsung/mct_var.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/samsung/exynos_platform.c diff -u src/sys/arch/arm/samsung/exynos_platform.c:1.9 src/sys/arch/arm/samsung/exynos_platform.c:1.10 --- src/sys/arch/arm/samsung/exynos_platform.c:1.9 Sat Mar 17 18:34:09 2018 +++ src/sys/arch/arm/samsung/exynos_platform.c Mon Jul 2 12:49:37 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: exynos_platform.c,v 1.9 2018/03/17 18:34:09 ryo Exp $ */ +/* $NetBSD: exynos_platform.c,v 1.10 2018/07/02 12:49:37 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared D. McNeill <jmcne...@invisible.ca> @@ -33,7 +33,7 @@ #include "ukbd.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: exynos_platform.c,v 1.9 2018/03/17 18:34:09 ryo Exp $"); +__KERNEL_RCSID(0, "$NetBSD: exynos_platform.c,v 1.10 2018/07/02 12:49:37 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -50,11 +50,10 @@ __KERNEL_RCSID(0, "$NetBSD: exynos_platf #include <arm/samsung/exynos_reg.h> #include <arm/samsung/exynos_var.h> +#include <arm/samsung/mct_var.h> #include <evbarm/exynos/platform.h> -#include <arm/cortex/gtmr_var.h> - #include <arm/fdt/arm_fdtvar.h> #define EXYNOS5_SWRESET_REG 0x10040400 @@ -123,12 +122,6 @@ exynos5_platform_reset(void) bus_space_write_4(bst, bsh, 0, 1); } -static void -exynos_platform_delay(u_int us) -{ - gtmr_delay(us); -} - static u_int exynos_platform_uart_freq(void) { @@ -142,7 +135,7 @@ static const struct arm_platform exynos5 .early_putchar = exynos_platform_early_putchar, .device_register = exynos_platform_device_register, .reset = exynos5_platform_reset, - .delay = exynos_platform_delay, + .delay = mct_delay, .uart_freq = exynos_platform_uart_freq, }; Index: src/sys/arch/arm/samsung/mct.c diff -u src/sys/arch/arm/samsung/mct.c:1.13 src/sys/arch/arm/samsung/mct.c:1.14 --- src/sys/arch/arm/samsung/mct.c:1.13 Sun Jul 1 23:21:43 2018 +++ src/sys/arch/arm/samsung/mct.c Mon Jul 2 12:49:37 2018 @@ -1,11 +1,11 @@ -/* $NetBSD: mct.c,v 1.13 2018/07/01 23:21:43 jmcneill Exp $ */ +/* $NetBSD: mct.c,v 1.14 2018/07/02 12:49:37 jmcneill Exp $ */ /*- - * Copyright (c) 2014 The NetBSD Foundation, Inc. + * Copyright (c) 2014-2018 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Reinoud Zandijk. + * by Reinoud Zandijk and Jared McNeill. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,7 +31,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: mct.c,v 1.13 2018/07/01 23:21:43 jmcneill Exp $"); +__KERNEL_RCSID(1, "$NetBSD: mct.c,v 1.14 2018/07/02 12:49:37 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -50,16 +50,25 @@ __KERNEL_RCSID(1, "$NetBSD: mct.c,v 1.13 #include <arm/samsung/mct_reg.h> #include <arm/samsung/mct_var.h> -#include <arm/cortex/gtmr_intr.h> -#include <arm/cortex/mpcore_var.h> -#include <arm/cortex/gtmr_var.h> - #include <dev/fdt/fdtvar.h> #include <arm/fdt/arm_fdtvar.h> +static struct mct_softc mct_sc; + static int mct_match(device_t, cfdata_t, void *); static void mct_attach(device_t, device_t, void *); +static u_int mct_get_timecount(struct timecounter *); + +static struct timecounter mct_timecounter = { + .tc_get_timecount = mct_get_timecount, + .tc_counter_mask = ~0u, + .tc_frequency = EXYNOS_F_IN_FREQ, + .tc_name = "MCT", + .tc_quality = 500, + .tc_priv = &mct_sc, +}; + CFATTACH_DECL_NEW(exyo_mct, 0, mct_match, mct_attach, NULL, NULL); static inline uint32_t @@ -85,20 +94,31 @@ mct_write_global(struct mct_softc *sc, b wreg = MCT_G_CNT_WSTAT; bit = (o == MCT_G_CNT_L) ? G_CNT_WSTAT_L : G_CNT_WSTAT_U; } else { - wreg = MCT_G_WSTAT; switch (o) { case MCT_G_COMP0_L: + wreg = MCT_G_WSTAT; bit = G_WSTAT_COMP0_L; break; case MCT_G_COMP0_U: + wreg = MCT_G_WSTAT; bit = G_WSTAT_COMP0_U; break; case MCT_G_COMP0_ADD_INCR: + wreg = MCT_G_WSTAT; bit = G_WSTAT_ADD_INCR; break; case MCT_G_TCON: + wreg = MCT_G_WSTAT; bit = G_WSTAT_TCON; break; + case MCT_G_CNT_L: + wreg = MCT_G_CNT_WSTAT; + bit = G_CNT_WSTAT_L; + break; + case MCT_G_CNT_U: + wreg = MCT_G_CNT_WSTAT; + bit = G_CNT_WSTAT_U; + break; default: /* all other registers */ return; @@ -120,7 +140,69 @@ mct_write_global(struct mct_softc *sc, b static void mct_fdt_cpu_hatch(void *priv, struct cpu_info *ci) { - gtmr_init_cpu_clock(ci); + panic("%s: not implemented", __func__); +} + +static int +mct_intr(void *arg) +{ + struct mct_softc * const sc = &mct_sc; + struct clockframe *frame = arg; + + mct_write_global(sc, MCT_G_INT_CSTAT, G_INT_CSTAT_CLEAR); + + hardclock(frame); + + return 1; +} + +static u_int +mct_get_timecount(struct timecounter *tc) +{ + struct mct_softc * const sc = tc->tc_priv; + + return mct_read_global(sc, MCT_G_CNT_L); +} + +static uint64_t +mct_read_gcnt(struct mct_softc *sc) +{ + uint32_t gcntl, gcntu; + + do { + gcntu = mct_read_global(sc, MCT_G_CNT_U); + gcntl = mct_read_global(sc, MCT_G_CNT_L); + } while (gcntu != mct_read_global(sc, MCT_G_CNT_U)); + + return ((uint64_t)gcntu << 32) | gcntl; +} + +static void +mct_cpu_initclocks(void) +{ + struct mct_softc * const sc = &mct_sc; + char intrstr[128]; + + if (!fdtbus_intr_str(sc->sc_phandle, 0, intrstr, sizeof(intrstr))) + panic("%s: failed to decode interrupt", __func__); + + sc->sc_global_ih = fdtbus_intr_establish(sc->sc_phandle, 0, IPL_CLOCK, + FDT_INTR_MPSAFE, mct_intr, NULL); + if (sc->sc_global_ih == NULL) + panic("%s: failed to establish timer interrupt on %s", __func__, intrstr); + + aprint_normal_dev(sc->sc_dev, "interrupting on %s\n", intrstr); + + /* Start the timer */ + const u_int autoinc = sc->sc_freq / hz; + const uint64_t comp0 = mct_read_gcnt(sc) + autoinc; + + mct_write_global(sc, MCT_G_TCON, G_TCON_START | G_TCON_COMP0_AUTOINC); + mct_write_global(sc, MCT_G_COMP0_ADD_INCR, autoinc); + mct_write_global(sc, MCT_G_COMP0_L, (uint32_t)comp0); + mct_write_global(sc, MCT_G_COMP0_U, (uint32_t)(comp0 >> 32)); + mct_write_global(sc, MCT_G_INT_ENB, G_INT_ENB_ENABLE); + mct_write_global(sc, MCT_G_TCON, G_TCON_START | G_TCON_COMP0_ENABLE | G_TCON_COMP0_AUTOINC); } static int @@ -149,9 +231,9 @@ mct_attach(device_t parent, device_t sel self->dv_private = sc; sc->sc_dev = self; + sc->sc_phandle = faa->faa_phandle; sc->sc_bst = faa->faa_bst; sc->sc_freq = EXYNOS_F_IN_FREQ; - error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh); if (error) { aprint_error(": couldn't map %#llx: %d", @@ -162,19 +244,31 @@ mct_attach(device_t parent, device_t sel aprint_naive("\n"); aprint_normal(": Exynos SoC multi core timer (64 bits)\n"); - /* Start the timer */ - uint32_t tcon = mct_read_global(sc, MCT_G_TCON); - tcon |= G_TCON_START; - mct_write_global(sc, MCT_G_TCON, tcon); - - /* Attach ARMv7 generic timer */ - struct mpcore_attach_args mpcaa = { - .mpcaa_name = "armgtmr", - .mpcaa_irq = IRQ_GTMR_PPI_VTIMER - }; - - config_found(self, &mpcaa, NULL); + tc_init(&mct_timecounter); arm_fdt_cpu_hatch_register(self, mct_fdt_cpu_hatch); - arm_fdt_timer_register(gtmr_cpu_initclocks); + arm_fdt_timer_register(mct_cpu_initclocks); +} + +void +mct_delay(u_int n) +{ + struct mct_softc * const sc = &mct_sc; + uint64_t cur, prev; + + if (sc->sc_bsh == 0) + panic("%s: mct driver not attached", __func__); + + const long incs_per_us = sc->sc_freq / 1000000; + long ticks = n * incs_per_us; + + prev = mct_read_gcnt(sc); + while (ticks > 0) { + cur = mct_read_gcnt(sc); + if (cur > prev) + ticks -= (cur - prev); + else + ticks -= (UINT64_MAX - cur + prev); + prev = cur; + } } Index: src/sys/arch/arm/samsung/mct_var.h diff -u src/sys/arch/arm/samsung/mct_var.h:1.5 src/sys/arch/arm/samsung/mct_var.h:1.6 --- src/sys/arch/arm/samsung/mct_var.h:1.5 Sun Jun 11 01:09:44 2017 +++ src/sys/arch/arm/samsung/mct_var.h Mon Jul 2 12:49:37 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: mct_var.h,v 1.5 2017/06/11 01:09:44 jmcneill Exp $ */ +/* $NetBSD: mct_var.h,v 1.6 2018/07/02 12:49:37 jmcneill Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -36,11 +36,11 @@ #include <sys/bus.h> #include <sys/device.h> -static struct mct_softc { +struct mct_softc { device_t sc_dev; bus_space_tag_t sc_bst; bus_space_handle_t sc_bsh; - uint32_t sc_irq; + int sc_phandle; uint32_t sc_freq; void *sc_global_ih; @@ -48,8 +48,7 @@ static struct mct_softc { uint64_t sc_lastintr; uint32_t sc_autoinc; struct evcnt sc_ev_missing_ticks; - -} mct_sc; +}; void mct_init_cpu_clock(struct cpu_info *ci); void mct_delay(u_int);