From owner-svn-src-all@freebsd.org Tue Apr 3 22:21:13 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id A0E3CF855DE; Tue, 3 Apr 2018 22:21:13 +0000 (UTC) (envelope-from mw@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4D47D78920; Tue, 3 Apr 2018 22:21:13 +0000 (UTC) (envelope-from mw@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 481282ADA; Tue, 3 Apr 2018 22:21:13 +0000 (UTC) (envelope-from mw@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w33MLDwY019505; Tue, 3 Apr 2018 22:21:13 GMT (envelope-from mw@FreeBSD.org) Received: (from mw@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w33MLDTE019502; Tue, 3 Apr 2018 22:21:13 GMT (envelope-from mw@FreeBSD.org) Message-Id: <201804032221.w33MLDTE019502@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mw set sender to mw@FreeBSD.org using -f From: Marcin Wojtas Date: Tue, 3 Apr 2018 22:21:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r331961 - in head/sys: arm/mv dts/arm X-SVN-Group: head X-SVN-Commit-Author: mw X-SVN-Commit-Paths: in head/sys: arm/mv dts/arm X-SVN-Commit-Revision: 331961 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 03 Apr 2018 22:21:13 -0000 Author: mw Date: Tue Apr 3 22:21:12 2018 New Revision: 331961 URL: https://svnweb.freebsd.org/changeset/base/331961 Log: Make Marvell AmadaXP timer driver more generic Store pointers to SoC specific functions in mv_timer_config structure and determine proper config in runtime based on compatible string from FDT. Compatible string for ArmadaXP timers is changed to match Linux FDT. Armada 38x uses generic Cortex-A9 timer and separate watchdog drivers, so it does not need to be supported by timer driver. Submitted by: Rafal Kozik Reviewed by: manu Obtained from: Semihalf Sponsored by: Stormshield Differential Revision: https://reviews.freebsd.org/D14741 Modified: head/sys/arm/mv/timer.c head/sys/dts/arm/db78460.dts Modified: head/sys/arm/mv/timer.c ============================================================================== --- head/sys/arm/mv/timer.c Tue Apr 3 22:15:53 2018 (r331960) +++ head/sys/arm/mv/timer.c Tue Apr 3 22:21:12 2018 (r331961) @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -60,18 +61,20 @@ __FBSDID("$FreeBSD$"); #define MV_WDT 0x2 #define MV_NONE 0x0 -#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X) -#define MV_CLOCK_SRC 25000000 /* Timers' 25MHz mode */ -#else -#define MV_CLOCK_SRC get_tclk() -#endif +#define MV_CLOCK_SRC_ARMV7 25000000 /* Timers' 25MHz mode */ -#if defined(SOC_MV_ARMADA38X) -#define WATCHDOG_TIMER 4 -#else -#define WATCHDOG_TIMER 2 -#endif +#define WATCHDOG_TIMER_ARMV5 2 +typedef void (*mv_watchdog_enable_t)(void); +typedef void (*mv_watchdog_disable_t)(void); + +struct mv_timer_config { + enum soc_family soc_family; + mv_watchdog_enable_t watchdog_enable; + mv_watchdog_disable_t watchdog_disable; + unsigned int clock_src; +}; + struct mv_timer_softc { struct resource * timer_res[2]; bus_space_tag_t timer_bst; @@ -79,6 +82,7 @@ struct mv_timer_softc { struct mtx timer_mtx; struct eventtimer et; boolean_t has_wdt; + struct mv_timer_config* config; }; static struct resource_spec mv_timer_spec[] = { @@ -89,8 +93,9 @@ static struct resource_spec mv_timer_spec[] = { /* Interrupt is not required by MV_WDT devices */ static struct ofw_compat_data mv_timer_compat[] = { + {"marvell,armada-380-timer", MV_NONE }, + {"marvell,armada-xp-timer", MV_TMR | MV_WDT }, {"mrvl,timer", MV_TMR | MV_WDT }, - {"marvell,armada-380-wdt", MV_WDT }, {NULL, MV_NONE } }; @@ -108,14 +113,42 @@ static void mv_set_timer_control(uint32_t); static uint32_t mv_get_timer(uint32_t); static void mv_set_timer(uint32_t, uint32_t); static void mv_set_timer_rel(uint32_t, uint32_t); -static void mv_watchdog_enable(void); -static void mv_watchdog_disable(void); static void mv_watchdog_event(void *, unsigned int, int *); static int mv_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period); static int mv_timer_stop(struct eventtimer *et); static void mv_setup_timers(void); +static void mv_watchdog_enable_armv5(void); +static void mv_watchdog_enable_armadaxp(void); +static void mv_watchdog_disable_armv5(void); +static void mv_watchdog_disable_armadaxp(void); + +#ifdef PLATFORM +void mv_delay(int usec, void* arg); +#endif + +static struct mv_timer_config timer_armadaxp_config = +{ + MV_SOC_ARMADA_XP, + &mv_watchdog_enable_armadaxp, + &mv_watchdog_disable_armadaxp, + MV_CLOCK_SRC_ARMV7, +}; +static struct mv_timer_config timer_armv5_config = +{ + MV_SOC_ARMV5, + &mv_watchdog_enable_armv5, + &mv_watchdog_disable_armv5, + 0, +}; + +static struct ofw_compat_data mv_timer_soc_config[] = { + {"marvell,armada-xp-timer", (uintptr_t)&timer_armadaxp_config }, + {"mrvl,timer", (uintptr_t)&timer_armv5_config }, + {NULL, (uintptr_t)NULL }, +}; + static struct timecounter mv_timer_timecounter = { .tc_get_timecount = mv_timer_get_timecount, .tc_name = "CPUTimer1", @@ -144,9 +177,7 @@ mv_timer_attach(device_t dev) int error; void *ihl; struct mv_timer_softc *sc; -#if !defined(SOC_MV_ARMADAXP) && !defined(SOC_MV_ARMADA38X) uint32_t irq_cause, irq_mask; -#endif if (timer_softc != NULL) return (ENXIO); @@ -154,6 +185,12 @@ mv_timer_attach(device_t dev) sc = (struct mv_timer_softc *)device_get_softc(dev); timer_softc = sc; + sc->config = (struct mv_timer_config*) + ofw_bus_search_compatible(dev, mv_timer_soc_config)->ocd_data; + + if (sc->config->clock_src == 0) + sc->config->clock_src = get_tclk(); + error = bus_alloc_resources(dev, mv_timer_spec, sc->timer_res); if (error) { device_printf(dev, "could not allocate resources\n"); @@ -163,13 +200,13 @@ mv_timer_attach(device_t dev) sc->timer_bst = rman_get_bustag(sc->timer_res[0]); sc->timer_bsh = rman_get_bushandle(sc->timer_res[0]); - sc->has_wdt = ofw_bus_has_prop(dev, "mrvl,has-wdt") || - ofw_bus_is_compatible(dev, "marvell,armada-380-wdt"); + sc->has_wdt = ofw_bus_has_prop(dev, "mrvl,has-wdt"); mtx_init(&timer_softc->timer_mtx, "watchdog", NULL, MTX_DEF); if (sc->has_wdt) { - mv_watchdog_disable(); + if (sc->config->watchdog_disable) + sc->config->watchdog_disable(); EVENTHANDLER_REGISTER(watchdog_list, mv_watchdog_event, sc, 0); } @@ -192,30 +229,33 @@ mv_timer_attach(device_t dev) } mv_setup_timers(); -#if !defined(SOC_MV_ARMADAXP) && !defined(SOC_MV_ARMADA38X) - irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE); - irq_cause &= IRQ_TIMER0_CLR; + if (sc->config->soc_family != MV_SOC_ARMADA_XP ) { + irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE); + irq_cause &= IRQ_TIMER0_CLR; - write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause); - irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK); - irq_mask |= IRQ_TIMER0_MASK; - irq_mask &= ~IRQ_TIMER1_MASK; - write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask); -#endif + write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause); + irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK); + irq_mask |= IRQ_TIMER0_MASK; + irq_mask &= ~IRQ_TIMER1_MASK; + write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask); + } sc->et.et_name = "CPUTimer0"; sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT; sc->et.et_quality = 1000; - sc->et.et_frequency = MV_CLOCK_SRC; + sc->et.et_frequency = sc->config->clock_src; sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency; sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; sc->et.et_start = mv_timer_start; sc->et.et_stop = mv_timer_stop; sc->et.et_priv = sc; et_register(&sc->et); - mv_timer_timecounter.tc_frequency = MV_CLOCK_SRC; + mv_timer_timecounter.tc_frequency = sc->config->clock_src; tc_init(&mv_timer_timecounter); +#ifdef PLATFORM + arm_set_delay(mv_delay, NULL); +#endif return (0); } @@ -260,8 +300,13 @@ mv_timer_get_timecount(struct timecounter *tc) return (INITIAL_TIMECOUNTER - mv_get_timer(1)); } +#ifdef PLATFORM void +mv_delay(int usec, void* arg) +#else +void DELAY(int usec) +#endif { uint32_t val, val_temp; int32_t nticks; @@ -275,7 +320,7 @@ DELAY(int usec) TSENTER(); val = mv_get_timer(1); - nticks = ((MV_CLOCK_SRC / 1000000 + 1) * usec); + nticks = ((timer_softc->config->clock_src / 1000000 + 1) * usec); while (nticks > 0) { val_temp = mv_get_timer(1); @@ -330,26 +375,14 @@ mv_set_timer_rel(uint32_t timer, uint32_t val) } static void -mv_watchdog_enable(void) +mv_watchdog_enable_armv5(void) { - uint32_t val, irq_cause; -#if !defined(SOC_MV_ARMADAXP) && !defined(SOC_MV_ARMADA38X) - uint32_t irq_mask; -#endif + uint32_t val, irq_cause, irq_mask; irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE); irq_cause &= IRQ_TIMER_WD_CLR; write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause); -#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X) - val = read_cpu_mp_clocks(WD_RSTOUTn_MASK); - val |= (WD_GLOBAL_MASK | WD_CPU0_MASK); - write_cpu_mp_clocks(WD_RSTOUTn_MASK, val); - - val = read_cpu_misc(RSTOUTn_MASK); - val &= ~RSTOUTn_MASK_WD; - write_cpu_misc(RSTOUTn_MASK, val); -#else irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK); irq_mask |= IRQ_TIMER_WD_MASK; write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask); @@ -357,44 +390,43 @@ mv_watchdog_enable(void) val = read_cpu_ctrl(RSTOUTn_MASK); val |= WD_RST_OUT_EN; write_cpu_ctrl(RSTOUTn_MASK, val); -#endif val = mv_get_timer_control(); -#if defined(SOC_MV_ARMADA38X) - val |= CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO | CPU_TIMER_WD_25MHZ_EN; -#elif defined(SOC_MV_ARMADAXP) - val |= CPU_TIMER2_EN | CPU_TIMER2_AUTO | CPU_TIMER_WD_25MHZ_EN; -#else val |= CPU_TIMER2_EN | CPU_TIMER2_AUTO; -#endif mv_set_timer_control(val); } static void -mv_watchdog_disable(void) +mv_watchdog_enable_armadaxp(void) { - uint32_t val, irq_cause; -#if !defined(SOC_MV_ARMADAXP) && !defined(SOC_MV_ARMADA38X) - uint32_t irq_mask; -#endif + uint32_t irq_cause, val; - val = mv_get_timer_control(); -#if defined(SOC_MV_ARMADA38X) - val &= ~(CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO); -#else - val &= ~(CPU_TIMER2_EN | CPU_TIMER2_AUTO); -#endif - mv_set_timer_control(val); + irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE); + irq_cause &= IRQ_TIMER_WD_CLR; + write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause); -#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X) val = read_cpu_mp_clocks(WD_RSTOUTn_MASK); - val &= ~(WD_GLOBAL_MASK | WD_CPU0_MASK); + val |= (WD_GLOBAL_MASK | WD_CPU0_MASK); write_cpu_mp_clocks(WD_RSTOUTn_MASK, val); val = read_cpu_misc(RSTOUTn_MASK); - val |= RSTOUTn_MASK_WD; - write_cpu_misc(RSTOUTn_MASK, RSTOUTn_MASK_WD); -#else + val &= ~RSTOUTn_MASK_WD; + write_cpu_misc(RSTOUTn_MASK, val); + + val = mv_get_timer_control(); + val |= CPU_TIMER2_EN | CPU_TIMER2_AUTO | CPU_TIMER_WD_25MHZ_EN; + mv_set_timer_control(val); +} + +static void +mv_watchdog_disable_armv5(void) +{ + uint32_t val, irq_cause,irq_mask; + + val = mv_get_timer_control(); + val &= ~(CPU_TIMER2_EN | CPU_TIMER2_AUTO); + mv_set_timer_control(val); + val = read_cpu_ctrl(RSTOUTn_MASK); val &= ~WD_RST_OUT_EN; write_cpu_ctrl(RSTOUTn_MASK, val); @@ -402,14 +434,34 @@ mv_watchdog_disable(void) irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK); irq_mask &= ~(IRQ_TIMER_WD_MASK); write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask); -#endif irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE); irq_cause &= IRQ_TIMER_WD_CLR; write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause); } +static void +mv_watchdog_disable_armadaxp(void) +{ + uint32_t val, irq_cause; + val = read_cpu_mp_clocks(WD_RSTOUTn_MASK); + val &= ~(WD_GLOBAL_MASK | WD_CPU0_MASK); + write_cpu_mp_clocks(WD_RSTOUTn_MASK, val); + + val = read_cpu_misc(RSTOUTn_MASK); + val |= RSTOUTn_MASK_WD; + write_cpu_misc(RSTOUTn_MASK, RSTOUTn_MASK_WD); + + irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE); + irq_cause &= IRQ_TIMER_WD_CLR; + write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause); + + val = mv_get_timer_control(); + val &= ~(CPU_TIMER2_EN | CPU_TIMER2_AUTO); + mv_set_timer_control(val); +} + /* * Watchdog event handler. */ @@ -420,20 +472,23 @@ mv_watchdog_event(void *arg, unsigned int cmd, int *er uint64_t ticks; mtx_lock(&timer_softc->timer_mtx); - if (cmd == 0) - mv_watchdog_disable(); - else { + if (cmd == 0) { + if (timer_softc->config->watchdog_disable != NULL) + timer_softc->config->watchdog_disable(); + } else { /* * Watchdog timeout is in nanosecs, calculation according to * watchdog(9) */ ns = (uint64_t)1 << (cmd & WD_INTERVAL); - ticks = (uint64_t)(ns * MV_CLOCK_SRC) / 1000000000; - if (ticks > MAX_WATCHDOG_TICKS) - mv_watchdog_disable(); - else { - mv_set_timer(WATCHDOG_TIMER, ticks); - mv_watchdog_enable(); + ticks = (uint64_t)(ns * timer_softc->config->clock_src) / 1000000000; + if (ticks > MAX_WATCHDOG_TICKS) { + if (timer_softc->config->watchdog_disable != NULL) + timer_softc->config->watchdog_disable(); + } else { + mv_set_timer(WATCHDOG_TIMER_ARMV5, ticks); + if (timer_softc->config->watchdog_enable != NULL) + timer_softc->config->watchdog_enable(); *error = 0; } } @@ -491,10 +546,12 @@ mv_setup_timers(void) val = mv_get_timer_control(); val &= ~(CPU_TIMER0_EN | CPU_TIMER0_AUTO); val |= CPU_TIMER1_EN | CPU_TIMER1_AUTO; -#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X) - /* Enable 25MHz mode */ - val |= CPU_TIMER0_25MHZ_EN | CPU_TIMER1_25MHZ_EN; -#endif + + if (timer_softc->config->soc_family == MV_SOC_ARMADA_XP) { + /* Enable 25MHz mode */ + val |= CPU_TIMER0_25MHZ_EN | CPU_TIMER1_25MHZ_EN; + } + mv_set_timer_control(val); timers_initialized = 1; } Modified: head/sys/dts/arm/db78460.dts ============================================================================== --- head/sys/dts/arm/db78460.dts Tue Apr 3 22:15:53 2018 (r331960) +++ head/sys/dts/arm/db78460.dts Tue Apr 3 22:21:12 2018 (r331961) @@ -85,7 +85,7 @@ }; timer@21840 { - compatible = "mrvl,timer"; + compatible = "marvell,armada-xp-timer"; reg = <0x21840 0x30>; interrupts = <5>; interrupt-parent = <&MPIC>;