Index: head/sys/arm/mv/timer.c =================================================================== --- head/sys/arm/mv/timer.c (revision 331960) +++ head/sys/arm/mv/timer.c (revision 331961) @@ -1,500 +1,557 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2006 Benno Rice. * Copyright (C) 2007-2008 MARVELL INTERNATIONAL LTD. * All rights reserved. * * Adapted to Marvell SoC by Semihalf. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_timer.c, rev 1 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #define INITIAL_TIMECOUNTER (0xffffffff) #define MAX_WATCHDOG_TICKS (0xffffffff) #define MV_TMR 0x1 #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; bus_space_handle_t timer_bsh; struct mtx timer_mtx; struct eventtimer et; boolean_t has_wdt; + struct mv_timer_config* config; }; static struct resource_spec mv_timer_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { SYS_RES_IRQ, 0, RF_ACTIVE | RF_OPTIONAL }, { -1, 0 } }; /* 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 } }; static struct mv_timer_softc *timer_softc = NULL; static int timers_initialized = 0; static int mv_timer_probe(device_t); static int mv_timer_attach(device_t); static int mv_hardclock(void *); static unsigned mv_timer_get_timecount(struct timecounter *); static uint32_t mv_get_timer_control(void); 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", .tc_frequency = 0, /* This is assigned on the fly in the init sequence */ .tc_counter_mask = ~0u, .tc_quality = 1000, }; static int mv_timer_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_search_compatible(dev, mv_timer_compat)->ocd_data == MV_NONE) return (ENXIO); device_set_desc(dev, "Marvell CPU Timer"); return (0); } static int 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); 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"); return (ENXIO); } 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); } if (ofw_bus_search_compatible(dev, mv_timer_compat)->ocd_data == MV_WDT) { /* Don't set timers for wdt-only entry. */ device_printf(dev, "only watchdog attached\n"); return (0); } else if (sc->timer_res[1] == NULL) { device_printf(dev, "no interrupt resource\n"); bus_release_resources(dev, mv_timer_spec, sc->timer_res); return (ENXIO); } if (bus_setup_intr(dev, sc->timer_res[1], INTR_TYPE_CLK, mv_hardclock, NULL, sc, &ihl) != 0) { bus_release_resources(dev, mv_timer_spec, sc->timer_res); device_printf(dev, "Could not setup interrupt.\n"); return (ENXIO); } 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); } static int mv_hardclock(void *arg) { struct mv_timer_softc *sc; uint32_t irq_cause; irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE); irq_cause &= IRQ_TIMER0_CLR; write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause); sc = (struct mv_timer_softc *)arg; if (sc->et.et_active) sc->et.et_event_cb(&sc->et, sc->et.et_arg); return (FILTER_HANDLED); } static device_method_t mv_timer_methods[] = { DEVMETHOD(device_probe, mv_timer_probe), DEVMETHOD(device_attach, mv_timer_attach), { 0, 0 } }; static driver_t mv_timer_driver = { "timer", mv_timer_methods, sizeof(struct mv_timer_softc), }; static devclass_t mv_timer_devclass; DRIVER_MODULE(timer, simplebus, mv_timer_driver, mv_timer_devclass, 0, 0); static unsigned 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; if (!timers_initialized) { for (; usec > 0; usec--) for (val = 100; val > 0; val--) __asm __volatile("nop" ::: "memory"); return; } 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); if (val > val_temp) nticks -= (val - val_temp); else nticks -= (val + (INITIAL_TIMECOUNTER - val_temp)); val = val_temp; } TSEXIT(); } static uint32_t mv_get_timer_control(void) { return (bus_space_read_4(timer_softc->timer_bst, timer_softc->timer_bsh, CPU_TIMER_CONTROL)); } static void mv_set_timer_control(uint32_t val) { bus_space_write_4(timer_softc->timer_bst, timer_softc->timer_bsh, CPU_TIMER_CONTROL, val); } static uint32_t mv_get_timer(uint32_t timer) { return (bus_space_read_4(timer_softc->timer_bst, timer_softc->timer_bsh, CPU_TIMER0 + timer * 0x8)); } static void mv_set_timer(uint32_t timer, uint32_t val) { bus_space_write_4(timer_softc->timer_bst, timer_softc->timer_bsh, CPU_TIMER0 + timer * 0x8, val); } static void mv_set_timer_rel(uint32_t timer, uint32_t val) { bus_space_write_4(timer_softc->timer_bst, timer_softc->timer_bsh, CPU_TIMER0_REL + timer * 0x8, 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); 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); 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. */ static void mv_watchdog_event(void *arg, unsigned int cmd, int *error) { uint64_t ns; 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; } } mtx_unlock(&timer_softc->timer_mtx); } static int mv_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period) { struct mv_timer_softc *sc; uint32_t val, val1; /* Calculate dividers. */ sc = (struct mv_timer_softc *)et->et_priv; if (period != 0) val = ((uint32_t)sc->et.et_frequency * period) >> 32; else val = 0; if (first != 0) val1 = ((uint32_t)sc->et.et_frequency * first) >> 32; else val1 = val; /* Apply configuration. */ mv_set_timer_rel(0, val); mv_set_timer(0, val1); val = mv_get_timer_control(); val |= CPU_TIMER0_EN; if (period != 0) val |= CPU_TIMER0_AUTO; else val &= ~CPU_TIMER0_AUTO; mv_set_timer_control(val); return (0); } static int mv_timer_stop(struct eventtimer *et) { uint32_t val; val = mv_get_timer_control(); val &= ~(CPU_TIMER0_EN | CPU_TIMER0_AUTO); mv_set_timer_control(val); return (0); } static void mv_setup_timers(void) { uint32_t val; mv_set_timer_rel(1, INITIAL_TIMECOUNTER); mv_set_timer(1, INITIAL_TIMECOUNTER); 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; } Index: head/sys/dts/arm/db78460.dts =================================================================== --- head/sys/dts/arm/db78460.dts (revision 331960) +++ head/sys/dts/arm/db78460.dts (revision 331961) @@ -1,323 +1,323 @@ /* * Copyright (c) 2010 The FreeBSD Foundation * Copyright (c) 2010-2011 Semihalf * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Marvell DB-78460 Device Tree Source. * * $FreeBSD$ */ /dts-v1/; / { model = "mrvl,DB-78460"; #address-cells = <1>; #size-cells = <1>; aliases { serial0 = &serial0; }; cpus { #address-cells = <1>; #size-cells = <0>; cpu@0 { device_type = "cpu"; compatible = "ARM,88VS584"; reg = <0x0>; d-cache-line-size = <32>; // 32 bytes i-cache-line-size = <32>; // 32 bytes d-cache-size = <0x8000>; // L1, 32K i-cache-size = <0x8000>; // L1, 32K timebase-frequency = <0>; bus-frequency = <200000000>; clock-frequency = <0>; }; }; memory { device_type = "memory"; reg = <0x0 0x80000000>; // 2G at 0x0 }; soc78460@d0000000 { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; ranges = <0x0 0xd0000000 0x00100000>; bus-frequency = <0>; MPIC: mpic@20a00 { interrupt-controller; #address-cells = <0>; #interrupt-cells = <1>; reg = <0x20a00 0x500 0x21870 0x58 0x20400 0x100>; compatible = "mrvl,mpic"; }; rtc@10300 { compatible = "mrvl,rtc"; reg = <0x10300 0x08>; }; timer@21840 { - compatible = "mrvl,timer"; + compatible = "marvell,armada-xp-timer"; reg = <0x21840 0x30>; interrupts = <5>; interrupt-parent = <&MPIC>; mrvl,has-wdt; }; twsi@11000 { #address-cells = <1>; #size-cells = <0>; compatible = "mrvl,twsi"; reg = <0x11000 0x20>; interrupts = <31>; interrupt-parent = <&MPIC>; }; twsi@11100 { #address-cells = <1>; #size-cells = <0>; compatible = "mrvl,twsi"; reg = <0x11100 0x20>; interrupts = <32>; interrupt-parent = <&MPIC>; }; serial0: serial@12000 { compatible = "snps,dw-apb-uart"; reg = <0x12000 0x20>; reg-shift = <2>; current-speed = <115200>; clock-frequency = <0>; interrupts = <41>; interrupt-parent = <&MPIC>; }; serial1: serial@12100 { compatible = "snps,dw-apb-uart"; reg = <0x12100 0x20>; reg-shift = <2>; current-speed = <115200>; clock-frequency = <0>; interrupts = <42>; interrupt-parent = <&MPIC>; }; serial2: serial@12200 { compatible = "snps,dw-apb-uart"; reg = <0x12200 0x20>; reg-shift = <2>; current-speed = <115200>; clock-frequency = <0>; interrupts = <43>; interrupt-parent = <&MPIC>; }; serial3: serial@12300 { compatible = "snps,dw-apb-uart"; reg = <0x12300 0x20>; reg-shift = <2>; current-speed = <115200>; clock-frequency = <0>; interrupts = <44>; interrupt-parent = <&MPIC>; }; MPP: mpp@10000 { #pin-cells = <2>; compatible = "mrvl,mpp"; reg = <0x18000 0x34>; pin-count = <68>; pin-map = < 0 1 /* MPP[0]: GE1_TXCLK */ 1 1 /* MPP[1]: GE1_TXCTL */ 2 1 /* MPP[2]: GE1_RXCTL */ 3 1 /* MPP[3]: GE1_RXCLK */ 4 1 /* MPP[4]: GE1_TXD[0] */ 5 1 /* MPP[5]: GE1_TXD[1] */ 6 1 /* MPP[6]: GE1_TXD[2] */ 7 1 /* MPP[7]: GE1_TXD[3] */ 8 1 /* MPP[8]: GE1_RXD[0] */ 9 1 /* MPP[9]: GE1_RXD[1] */ 10 1 /* MPP[10]: GE1_RXD[2] */ 11 1 /* MPP[11]: GE1_RXD[3] */ 12 2 /* MPP[13]: SYSRST_OUTn */ 13 2 /* MPP[13]: SYSRST_OUTn */ 14 2 /* MPP[14]: SATA1_ACTn */ 15 2 /* MPP[15]: SATA0_ACTn */ 16 2 /* MPP[16]: UA2_TXD */ 17 2 /* MPP[17]: UA2_RXD */ 18 2 /* MPP[18]: */ 19 2 /* MPP[19]: */ 20 2 /* MPP[20]: */ 21 2 /* MPP[21]: */ 22 2 /* MPP[22]: UA3_TXD */ 23 2 24 0 25 0 26 0 27 0 28 4 29 0 30 1 31 1 32 1 33 1 34 1 35 1 36 1 37 1 38 1 39 1 40 0 41 3 42 1 43 1 44 2 45 2 46 4 47 3 48 0 49 1 50 1 51 1 52 1 53 1 54 1 55 1 56 1 57 0 58 1 59 1 60 1 61 1 62 1 63 1 64 1 65 1 66 1 67 2 >; }; usb@50000 { compatible = "mrvl,usb-ehci", "usb-ehci"; reg = <0x50000 0x1000>; interrupts = <124 45>; interrupt-parent = <&MPIC>; }; usb@51000 { compatible = "mrvl,usb-ehci", "usb-ehci"; reg = <0x51000 0x1000>; interrupts = <124 46>; interrupt-parent = <&MPIC>; }; usb@52000 { compatible = "mrvl,usb-ehci", "usb-ehci"; reg = <0x52000 0x1000>; interrupts = <124 47>; interrupt-parent = <&MPIC>; }; enet0: ethernet@72000 { #address-cells = <1>; #size-cells = <1>; model = "V2"; compatible = "mrvl,ge"; reg = <0x72000 0x2000>; ranges = <0x0 0x72000 0x2000>; local-mac-address = [ 00 04 01 07 84 60 ]; interrupts = <67 68 122 >; interrupt-parent = <&MPIC>; phy-handle = <&phy0>; has-neta; mdio@0 { #address-cells = <1>; #size-cells = <0>; compatible = "mrvl,mdio"; phy0: ethernet-phy@0 { reg = <0x0>; }; phy1: ethernet-phy@1 { reg = <0x1>; }; phy2: ethernet-phy@2 { reg = <0x19>; }; phy3: ethernet-phy@3 { reg = <0x1b>; }; }; }; sata@A0000 { compatible = "mrvl,sata"; reg = <0xA0000 0x6000>; interrupts = <55>; interrupt-parent = <&MPIC>; }; }; pci0: pcie@d0040000 { compatible = "mrvl,pcie"; device_type = "pci"; #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; reg = <0xd0040000 0x2000>; bus-range = <0 255>; ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000 0x01000000 0x0 0x00000000 0xa0000000 0x0 0x08000000>; clock-frequency = <33333333>; interrupt-parent = <&MPIC>; interrupts = <120>; interrupt-map-mask = <0xf800 0x0 0x0 0x7>; interrupt-map = < 0x0800 0x0 0x0 0x1 &MPIC 0x3A 0x0800 0x0 0x0 0x2 &MPIC 0x3A 0x0800 0x0 0x0 0x3 &MPIC 0x3A 0x0800 0x0 0x0 0x4 &MPIC 0x3A >; }; sram@ffff0000 { compatible = "mrvl,cesa-sram"; reg = <0xffff0000 0x00010000>; }; chosen { stdin = "serial0"; stdout = "serial0"; stddbg = "serial0"; }; };