From owner-svn-src-all@freebsd.org Fri Jun 19 15:32:56 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 0903F34FF36; Fri, 19 Jun 2020 15:32:56 +0000 (UTC) (envelope-from mmel@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49pN9M6SP9z4JnV; Fri, 19 Jun 2020 15:32:55 +0000 (UTC) (envelope-from mmel@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 D8B341D587; Fri, 19 Jun 2020 15:32:55 +0000 (UTC) (envelope-from mmel@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 05JFWt3L052166; Fri, 19 Jun 2020 15:32:55 GMT (envelope-from mmel@FreeBSD.org) Received: (from mmel@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 05JFWttZ052165; Fri, 19 Jun 2020 15:32:55 GMT (envelope-from mmel@FreeBSD.org) Message-Id: <202006191532.05JFWttZ052165@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mmel set sender to mmel@FreeBSD.org using -f From: Michal Meloun Date: Fri, 19 Jun 2020 15:32:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r362386 - head/sys/arm/mv/armada38x X-SVN-Group: head X-SVN-Commit-Author: mmel X-SVN-Commit-Paths: head/sys/arm/mv/armada38x X-SVN-Commit-Revision: 362386 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.33 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: Fri, 19 Jun 2020 15:32:56 -0000 Author: mmel Date: Fri Jun 19 15:32:55 2020 New Revision: 362386 URL: https://svnweb.freebsd.org/changeset/base/362386 Log: Add specific stub for ARMADA 8k SoC to Marvell RTC driver. The AXI bridge is different between ARMADA 38x and 8K, and both platforms needs specific setup to mitigate HW issues with accessing RTC registers. MFC after: 2 weeks Modified: head/sys/arm/mv/armada38x/armada38x_rtc.c Modified: head/sys/arm/mv/armada38x/armada38x_rtc.c ============================================================================== --- head/sys/arm/mv/armada38x/armada38x_rtc.c Fri Jun 19 15:21:33 2020 (r362385) +++ head/sys/arm/mv/armada38x/armada38x_rtc.c Fri Jun 19 15:32:55 2020 (r362386) @@ -72,14 +72,27 @@ __FBSDID("$FreeBSD$"); #define MV_RTC_LOCK(sc) mtx_lock_spin(&(sc)->mutex) #define MV_RTC_UNLOCK(sc) mtx_unlock_spin(&(sc)->mutex) -#define RTC_BRIDGE_TIMING_CTRL 0x0 -#define RTC_WRCLK_PERIOD_SHIFT 0 -#define RTC_WRCLK_PERIOD_MASK 0x00000003FF -#define RTC_WRCLK_PERIOD_MAX 0x3FF -#define RTC_READ_OUTPUT_DELAY_SHIFT 26 -#define RTC_READ_OUTPUT_DELAY_MASK 0x007C000000 -#define RTC_READ_OUTPUT_DELAY_MAX 0x1F +#define A38X_RTC_BRIDGE_TIMING_CTRL 0x0 +#define A38X_RTC_WRCLK_PERIOD_SHIFT 0 +#define A38X_RTC_WRCLK_PERIOD_MASK 0x00000003FF +#define A38X_RTC_WRCLK_PERIOD_MAX 0x3FF +#define A38X_RTC_READ_OUTPUT_DELAY_SHIFT 26 +#define A38X_RTC_READ_OUTPUT_DELAY_MASK 0x007C000000 +#define A38X_RTC_READ_OUTPUT_DELAY_MAX 0x1F +#define A8K_RTC_BRIDGE_TIMING_CTRL0 0x0 +#define A8K_RTC_WRCLK_PERIOD_SHIFT 0 +#define A8K_RTC_WRCLK_PERIOD_MASK 0x000000FFFF +#define A8K_RTC_WRCLK_PERIOD_VAL 0x3FF +#define A8K_RTC_WRCLK_SETUP_SHIFT 16 +#define A8K_RTC_WRCLK_SETUP_MASK 0x00FFFF0000 +#define A8K_RTC_WRCLK_SETUP_VAL 29 +#define A8K_RTC_BRIDGE_TIMING_CTRL1 0x4 +#define A8K_RTC_READ_OUTPUT_DELAY_SHIFT 0 +#define A8K_RTC_READ_OUTPUT_DELAY_MASK 0x000000FFFF +#define A8K_RTC_READ_OUTPUT_DELAY_VAL 0x3F + + #define RTC_RES 0 #define RTC_SOC_RES 1 @@ -94,6 +107,7 @@ struct mv_rtc_softc { device_t dev; struct resource *res[2]; struct mtx mutex; + int rtc_type; }; static int mv_rtc_probe(device_t dev); @@ -107,7 +121,8 @@ static inline uint32_t mv_rtc_reg_read(struct mv_rtc_s bus_size_t off); static inline int mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off, uint32_t val); -static inline void mv_rtc_configure_bus(struct mv_rtc_softc *sc); +static inline void mv_rtc_configure_bus_a38x(struct mv_rtc_softc *sc); +static inline void mv_rtc_configure_bus_a8k(struct mv_rtc_softc *sc); static device_method_t mv_rtc_methods[] = { DEVMETHOD(device_probe, mv_rtc_probe), @@ -126,10 +141,13 @@ static driver_t mv_rtc_driver = { sizeof(struct mv_rtc_softc), }; +#define RTC_A38X 1 +#define RTC_A8K 2 + static struct ofw_compat_data mv_rtc_compat[] = { - {"marvell,armada-380-rtc", true}, - {"marvell,armada-8k-rtc", true}, - {NULL, false}, + {"marvell,armada-380-rtc", RTC_A38X}, + {"marvell,armada-8k-rtc", RTC_A8K}, + {NULL, 0}, }; static devclass_t mv_rtc_devclass; @@ -198,20 +216,29 @@ mv_rtc_attach(device_t dev) sc = device_get_softc(dev); sc->dev = dev; + sc->rtc_type = ofw_bus_search_compatible(dev, mv_rtc_compat)->ocd_data; - clock_register(dev, RTC_RES_US); - mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_SPIN); ret = bus_alloc_resources(dev, res_spec, sc->res); - if (ret != 0) { device_printf(dev, "could not allocate resources\n"); mtx_destroy(&sc->mutex); return (ENXIO); } - mv_rtc_configure_bus(sc); + switch (sc->rtc_type) { + case RTC_A38X: + mv_rtc_configure_bus_a38x(sc); + break; + case RTC_A8K: + mv_rtc_configure_bus_a8k(sc); + break; + default: + panic("Unknown RTC type: %d", sc->rtc_type); + } + clock_register(dev, RTC_RES_US); + return (0); } @@ -239,13 +266,15 @@ mv_rtc_gettime(device_t dev, struct timespec *ts) MV_RTC_LOCK(sc); /* - * According to HW Errata if more than one second between - * two time reads is detected, then read once again + * According to HW Errata, if more than one second is detected + * between two time reads, then at least one of the reads gave + * an invalid value. */ - val = mv_rtc_reg_read(sc, RTC_TIME); - val_check = mv_rtc_reg_read(sc, RTC_TIME); - if (val_check - val > 1) + do { + val = mv_rtc_reg_read(sc, RTC_TIME); + DELAY(100); val_check = mv_rtc_reg_read(sc, RTC_TIME); + } while ((val_check - val) > 1); MV_RTC_UNLOCK(sc); @@ -284,7 +313,6 @@ mv_rtc_settime(device_t dev, struct timespec *ts) mv_rtc_reg_write(sc, RTC_STATUS, 0x0); mv_rtc_reg_write(sc, RTC_STATUS, 0x0); mv_rtc_reg_write(sc, RTC_TIME, ts->tv_sec); - MV_RTC_UNLOCK(sc); return (0); @@ -313,13 +341,30 @@ mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t o } static inline void -mv_rtc_configure_bus(struct mv_rtc_softc *sc) +mv_rtc_configure_bus_a38x(struct mv_rtc_softc *sc) { int val; - val = bus_read_4(sc->res[RTC_SOC_RES], RTC_BRIDGE_TIMING_CTRL); - val &= ~(RTC_WRCLK_PERIOD_MASK | RTC_READ_OUTPUT_DELAY_MASK); - val |= RTC_WRCLK_PERIOD_MAX << RTC_WRCLK_PERIOD_SHIFT; - val |= RTC_READ_OUTPUT_DELAY_MAX << RTC_READ_OUTPUT_DELAY_SHIFT; - bus_write_4(sc->res[RTC_SOC_RES], RTC_BRIDGE_TIMING_CTRL, val); + val = bus_read_4(sc->res[RTC_SOC_RES], A38X_RTC_BRIDGE_TIMING_CTRL); + val &= ~(A38X_RTC_WRCLK_PERIOD_MASK | A38X_RTC_READ_OUTPUT_DELAY_MASK); + val |= A38X_RTC_WRCLK_PERIOD_MAX << A38X_RTC_WRCLK_PERIOD_SHIFT; + val |= A38X_RTC_READ_OUTPUT_DELAY_MAX << A38X_RTC_READ_OUTPUT_DELAY_SHIFT; + bus_write_4(sc->res[RTC_SOC_RES], A38X_RTC_BRIDGE_TIMING_CTRL, val); +} + +static inline void +mv_rtc_configure_bus_a8k(struct mv_rtc_softc *sc) +{ + int val; + + val = bus_read_4(sc->res[RTC_SOC_RES], A8K_RTC_BRIDGE_TIMING_CTRL0); + val &= ~(A8K_RTC_WRCLK_PERIOD_MASK | A8K_RTC_WRCLK_SETUP_MASK); + val |= A8K_RTC_WRCLK_PERIOD_VAL << A8K_RTC_WRCLK_PERIOD_SHIFT; + val |= A8K_RTC_WRCLK_SETUP_VAL << A8K_RTC_WRCLK_SETUP_SHIFT; + bus_write_4(sc->res[RTC_SOC_RES], A8K_RTC_BRIDGE_TIMING_CTRL1, val); + + val = bus_read_4(sc->res[RTC_SOC_RES], A8K_RTC_BRIDGE_TIMING_CTRL0); + val &= ~A8K_RTC_READ_OUTPUT_DELAY_MASK; + val |= A8K_RTC_READ_OUTPUT_DELAY_VAL << A8K_RTC_READ_OUTPUT_DELAY_SHIFT; + bus_write_4(sc->res[RTC_SOC_RES], A8K_RTC_BRIDGE_TIMING_CTRL1, val); }