svn commit: r208932 - in user/jmallett/octeon/sys/mips: cavium conf
Juli Mallett
jmallett at FreeBSD.org
Wed Jun 9 02:07:52 UTC 2010
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 at 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"
More information about the svn-src-user
mailing list