Skip site navigation (1)Skip section navigation (2)
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(&reg, 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>