Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/samsung Add a proper MCT driver rather than rel...
details: https://anonhg.NetBSD.org/src/rev/a966e5e8f41a
branches: trunk
changeset: 323822:a966e5e8f41a
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Jul 02 12:49:37 2018 +0000
description:
Add a proper MCT driver rather than relying on ARM Generic Timer (which
may not be functional or even present).
diffstat:
sys/arch/arm/samsung/exynos_platform.c | 15 +--
sys/arch/arm/samsung/mct.c | 142 +++++++++++++++++++++++++++-----
sys/arch/arm/samsung/mct_var.h | 9 +-
3 files changed, 126 insertions(+), 40 deletions(-)
diffs (truncated from 303 to 300 lines):
diff -r f787931c03f9 -r a966e5e8f41a sys/arch/arm/samsung/exynos_platform.c
--- a/sys/arch/arm/samsung/exynos_platform.c Mon Jul 02 12:47:19 2018 +0000
+++ b/sys/arch/arm/samsung/exynos_platform.c Mon Jul 02 12:49:37 2018 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
#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 @@
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 @@
.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,
};
diff -r f787931c03f9 -r a966e5e8f41a sys/arch/arm/samsung/mct.c
--- a/sys/arch/arm/samsung/mct.c Mon Jul 02 12:47:19 2018 +0000
+++ b/sys/arch/arm/samsung/mct.c Mon Jul 02 12:49:37 2018 +0000
@@ -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 @@
#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 @@
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 @@
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 @@
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 @@
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;
+ }
+}
diff -r f787931c03f9 -r a966e5e8f41a sys/arch/arm/samsung/mct_var.h
--- a/sys/arch/arm/samsung/mct_var.h Mon Jul 02 12:47:19 2018 +0000
+++ b/sys/arch/arm/samsung/mct_var.h Mon Jul 02 12:49:37 2018 +0000
@@ -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 @@
uint64_t sc_lastintr;
uint32_t sc_autoinc;
struct evcnt sc_ev_missing_ticks;
-
-} mct_sc;
+};
Home |
Main Index |
Thread Index |
Old Index