Date: Wed, 9 Jun 2010 02:07:52 +0000 (UTC) From: Juli Mallett <jmallett@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r208932 - in user/jmallett/octeon/sys/mips: cavium conf Message-ID: <201006090207.o5927qoA080556@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jmallett Date: Wed Jun 9 02:07:51 2010 New Revision: 208932 URL: http://svn.freebsd.org/changeset/base/208932 Log: Add support for a simple realtime clock implemented via the Simple Executive's RTC functions. Added: user/jmallett/octeon/sys/mips/cavium/octeon_rtc.c Modified: user/jmallett/octeon/sys/mips/cavium/files.octeon1 user/jmallett/octeon/sys/mips/cavium/octeon_ds1337.c user/jmallett/octeon/sys/mips/conf/OCTEON1.hints Modified: user/jmallett/octeon/sys/mips/cavium/files.octeon1 ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/files.octeon1 Wed Jun 9 02:04:41 2010 (r208931) +++ user/jmallett/octeon/sys/mips/cavium/files.octeon1 Wed Jun 9 02:07:51 2010 (r208932) @@ -4,9 +4,11 @@ mips/cavium/asm_octeon.S optional smp mips/cavium/ciu.c standard mips/cavium/obio.c optional uart +mips/cavium/octeon_ds1337.c standard mips/cavium/octeon_ebt3000_cf.c optional cf mips/cavium/octeon_machdep.c standard mips/cavium/octeon_mp.c optional smp +mips/cavium/octeon_rtc.c standard mips/cavium/uart_bus_octeonusart.c optional uart mips/cavium/uart_cpu_octeonusart.c optional uart mips/cavium/uart_dev_oct16550.c optional uart @@ -47,7 +49,10 @@ contrib/octeon-sdk/cvmx-spi.c optional contrib/octeon-sdk/cvmx-spi4000.c optional octe contrib/octeon-sdk/cvmx-twsi.c optional octe +# XXX Some files could be excluded in some configurations. Making them +# optional but on in the default config would seem reasonable. contrib/octeon-sdk/cvmx-bootmem.c standard contrib/octeon-sdk/cvmx-sysinfo.c standard +contrib/octeon-sdk/cvmx-thunder.c standard contrib/octeon-sdk/cvmx-warn.c standard contrib/octeon-sdk/octeon-model.c standard Modified: user/jmallett/octeon/sys/mips/cavium/octeon_ds1337.c ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octeon_ds1337.c Wed Jun 9 02:04:41 2010 (r208931) +++ user/jmallett/octeon/sys/mips/cavium/octeon_ds1337.c Wed Jun 9 02:07:51 2010 (r208932) @@ -50,25 +50,16 @@ * */ -#include <time.h> -#include "cvmx-config.h" -#include "cvmx.h" -#include "cvmx-sysinfo.h" -#include "cvmx-cn3010-evb-hs5.h" -#include "cvmx-twsi.h" +#include <sys/param.h> +#include <sys/timespec.h> +#include <sys/clock.h> +#include <sys/libkern.h> + +#include <contrib/octeon-sdk/cvmx.h> +#include <contrib/octeon-sdk/cvmx-cn3010-evb-hs5.h> +#include <contrib/octeon-sdk/cvmx-twsi.h> - -static inline uint8_t bin2bcd(uint8_t bin) -{ - return (bin / 10) << 4 | (bin % 10); -} - -static inline uint8_t bcd2bin(uint8_t bcd) -{ - return (bcd >> 4) * 10 + (bcd & 0xf); -} - -#define TM_CHECK(_expr, _msg) \ +#define CT_CHECK(_expr, _msg) \ do { \ if (_expr) { \ cvmx_dprintf("Warning: RTC has invalid %s field\n", (_msg)); \ @@ -76,20 +67,20 @@ static inline uint8_t bcd2bin(uint8_t bc } \ } while(0); -static int validate_tm_struct(struct tm * tms) +static int validate_ct_struct(struct clocktime *ct) { int rc = 0; - if (!tms) + if (!ct) return -1; - TM_CHECK(tms->tm_sec < 0 || tms->tm_sec > 60, "second"); /* + Leap sec */ - TM_CHECK(tms->tm_min < 0 || tms->tm_min > 59, "minute"); - TM_CHECK(tms->tm_hour < 0 || tms->tm_hour > 23, "hour"); - TM_CHECK(tms->tm_mday < 1 || tms->tm_mday > 31, "day"); - TM_CHECK(tms->tm_wday < 0 || tms->tm_wday > 6, "day of week"); - TM_CHECK(tms->tm_mon < 0 || tms->tm_mon > 11, "month"); - TM_CHECK(tms->tm_year < 0 || tms->tm_year > 200,"year"); + CT_CHECK(ct->sec < 0 || ct->sec > 60, "second"); /* + Leap sec */ + CT_CHECK(ct->min < 0 || ct->min > 59, "minute"); + CT_CHECK(ct->hour < 0 || ct->hour > 23, "hour"); + CT_CHECK(ct->day < 1 || ct->day > 31, "day"); + CT_CHECK(ct->dow < 0 || ct->dow > 6, "day of week"); + CT_CHECK(ct->mon < 0 || ct->mon > 11, "month"); + CT_CHECK(ct->year < 0 || ct->year > 200,"year"); return rc; } @@ -102,14 +93,14 @@ static int validate_tm_struct(struct tm uint32_t cvmx_rtc_ds1337_read(void) { int i, retry; - uint32_t time; uint8_t reg[8]; uint8_t sec; - struct tm tms; + struct clocktime ct; + struct timespec ts; memset(®, 0, sizeof(reg)); - memset(&tms, 0, sizeof(struct tm)); + memset(&ct, 0, sizeof(ct)); for(retry=0; retry<2; retry++) { @@ -123,25 +114,28 @@ uint32_t cvmx_rtc_ds1337_read(void) break; /* Time did not roll-over, value is correct */ } - tms.tm_sec = bcd2bin(reg[0] & 0x7f); - tms.tm_min = bcd2bin(reg[1] & 0x7f); - tms.tm_hour = bcd2bin(reg[2] & 0x3f); + ct.sec = bcd2bin(reg[0] & 0x7f); + ct.min = bcd2bin(reg[1] & 0x7f); + ct.hour = bcd2bin(reg[2] & 0x3f); if ((reg[2] & 0x40) && (reg[2] & 0x20)) /* AM/PM format and is PM time */ { - tms.tm_hour = (tms.tm_hour + 12) % 24; + ct.hour = (ct.hour + 12) % 24; } - tms.tm_wday = (reg[3] & 0x7) - 1; /* Day of week field is 0..6 */ - tms.tm_mday = bcd2bin(reg[4] & 0x3f); - tms.tm_mon = bcd2bin(reg[5] & 0x1f) - 1; /* Month field is 0..11 */ - tms.tm_year = ((reg[5] & 0x80) ? 100 : 0) + bcd2bin(reg[6]); + ct.dow = (reg[3] & 0x7) - 1; /* Day of week field is 0..6 */ + ct.day = bcd2bin(reg[4] & 0x3f); + ct.mon = bcd2bin(reg[5] & 0x1f) - 1; /* Month field is 0..11 */ + ct.year = ((reg[5] & 0x80) ? 100 : 0) + bcd2bin(reg[6]); - if (validate_tm_struct(&tms)) + if (validate_ct_struct(&ct)) cvmx_dprintf("Warning: RTC calendar is not configured properly\n"); - time = mktime(&tms); + if (clock_ct_to_ts(&ct, &ts) != 0) { + cvmx_dprintf("Warning: RTC calendar is not configured properly\n"); + return 0; + } - return time; + return ts.tv_sec; } /* @@ -150,32 +144,34 @@ uint32_t cvmx_rtc_ds1337_read(void) */ int cvmx_rtc_ds1337_write(uint32_t time) { + struct clocktime ct; + struct timespec ts; int i, rc, retry; - struct tm tms; uint8_t reg[8]; uint8_t sec; - time_t time_from_epoch = time; + ts.tv_sec = time; + ts.tv_nsec = 0; - localtime_r(&time_from_epoch, &tms); + clock_ts_to_ct(&ts, &ct); - if (validate_tm_struct(&tms)) + if (validate_ct_struct(&ct)) { cvmx_dprintf("Error: RTC was passed wrong calendar values, write failed\n"); - goto tm_invalid; + goto ct_invalid; } - reg[0] = bin2bcd(tms.tm_sec); - reg[1] = bin2bcd(tms.tm_min); - reg[2] = bin2bcd(tms.tm_hour); /* Force 0..23 format even if using AM/PM */ - reg[3] = bin2bcd(tms.tm_wday + 1); - reg[4] = bin2bcd(tms.tm_mday); - reg[5] = bin2bcd(tms.tm_mon + 1); - if (tms.tm_year >= 100) /* Set century bit*/ + reg[0] = bin2bcd(ct.sec); + reg[1] = bin2bcd(ct.min); + reg[2] = bin2bcd(ct.hour); /* Force 0..23 format even if using AM/PM */ + reg[3] = bin2bcd(ct.dow + 1); + reg[4] = bin2bcd(ct.day); + reg[5] = bin2bcd(ct.mon + 1); + if (ct.year >= 100) /* Set century bit*/ { reg[5] |= 0x80; } - reg[6] = bin2bcd(tms.tm_year % 100); + reg[6] = bin2bcd(ct.year % 100); /* Lockless write: detects the infrequent roll-over and retries */ for(retry=0; retry<2; retry++) @@ -193,7 +189,7 @@ int cvmx_rtc_ds1337_write(uint32_t time) return (rc ? -1 : 0); - tm_invalid: + ct_invalid: return -1; } Added: user/jmallett/octeon/sys/mips/cavium/octeon_rtc.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/jmallett/octeon/sys/mips/cavium/octeon_rtc.c Wed Jun 9 02:07:51 2010 (r208932) @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org> + * 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. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/clock.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/module.h> + +#include <contrib/octeon-sdk/cvmx.h> +#include <contrib/octeon-sdk/cvmx-rtc.h> + +#include "clock_if.h" + +static int octeon_rtc_attach(device_t dev); +static int octeon_rtc_probe(device_t dev); + +static int octeon_rtc_settime(device_t dev, struct timespec *ts); +static int octeon_rtc_gettime(device_t dev, struct timespec *ts); + +static device_method_t octeon_rtc_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, octeon_rtc_probe), + DEVMETHOD(device_attach, octeon_rtc_attach), + + /* clock interface */ + DEVMETHOD(clock_gettime, octeon_rtc_gettime), + DEVMETHOD(clock_settime, octeon_rtc_settime), + + { 0, 0 } +}; + +static driver_t octeon_rtc_driver = { + "rtc", + octeon_rtc_methods, + 0 +}; +static devclass_t octeon_rtc_devclass; +DRIVER_MODULE(rtc, nexus, octeon_rtc_driver, octeon_rtc_devclass, 0, 0); + +static int +octeon_rtc_probe(device_t dev) +{ + cvmx_rtc_options_t supported; + + if (device_get_unit(dev) != 0) + return (ENXIO); + + supported = cvmx_rtc_supported(); + if (supported == 0) + return (ENXIO); + + device_set_desc(dev, "Cavium Octeon Realtime Clock"); + return (0); +} + +static int +octeon_rtc_attach(device_t dev) +{ + cvmx_rtc_options_t supported; + + supported = cvmx_rtc_supported(); + if ((supported & CVMX_RTC_READ) == 0) + return (ENXIO); + + clock_register(dev, 1000000); + return (0); +} + +static int +octeon_rtc_settime(device_t dev, struct timespec *ts) +{ + cvmx_rtc_options_t supported; + uint32_t status; + + supported = cvmx_rtc_supported(); + if ((supported & CVMX_RTC_WRITE) == 0) + return (ENOTSUP); + + status = cvmx_rtc_write(ts->tv_sec); + if (status != 0) + return (EINVAL); + + return (0); +} + +static int +octeon_rtc_gettime(device_t dev, struct timespec *ts) +{ + uint32_t secs; + + secs = cvmx_rtc_read(); + if (secs == 0) + return (ENOTSUP); + + ts->tv_sec = secs; + ts->tv_nsec = 0; + + return (0); +} Modified: user/jmallett/octeon/sys/mips/conf/OCTEON1.hints ============================================================================== --- user/jmallett/octeon/sys/mips/conf/OCTEON1.hints Wed Jun 9 02:04:41 2010 (r208931) +++ user/jmallett/octeon/sys/mips/conf/OCTEON1.hints Wed Jun 9 02:07:51 2010 (r208932) @@ -3,6 +3,7 @@ # All these values are complete nonsense... hw.uart.console="io:0x1" hint.ciu.0.at="nexus" +hint.rtc.0.at="nexus" hint.obio.0.at="ciu" hint.obio.0.maddr="0x1" hint.obio.0.msize="0x1"
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201006090207.o5927qoA080556>