Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 15 Nov 2015 19:30:56 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r290872 - projects/powernv/powerpc/powernv
Message-ID:  <201511151930.tAFJUuX2069068@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Sun Nov 15 19:30:56 2015
New Revision: 290872
URL: https://svnweb.freebsd.org/changeset/base/290872

Log:
  Let the system read the OPAL RTC.
  
  Sponsored by:	FreeBSD Foundation

Modified:
  projects/powernv/powerpc/powernv/opal.h
  projects/powernv/powerpc/powernv/opal_dev.c

Modified: projects/powernv/powerpc/powernv/opal.h
==============================================================================
--- projects/powernv/powerpc/powernv/opal.h	Sun Nov 15 18:56:58 2015	(r290871)
+++ projects/powernv/powerpc/powernv/opal.h	Sun Nov 15 19:30:56 2015	(r290872)
@@ -40,8 +40,11 @@ int opal_call(uint64_t token, ...);
 
 #define OPAL_CONSOLE_WRITE		1
 #define OPAL_CONSOLE_READ		2
+#define OPAL_RTC_READ			3
+#define OPAL_RTC_WRITE			4
 #define	OPAL_CEC_POWER_DOWN		5
 #define	OPAL_CEC_REBOOT			6
+#define	OPAL_POLL_EVENTS		10
 #define	OPAL_PCI_CONFIG_READ_BYTE	13
 #define	OPAL_PCI_CONFIG_READ_HALF_WORD	14
 #define	OPAL_PCI_CONFIG_READ_WORD	15
@@ -51,7 +54,7 @@ int opal_call(uint64_t token, ...);
 #define	OPAL_SET_XIVE			19
 #define	OPAL_GET_XIVE			20
 #define	OPAL_PCI_SET_PE			31
-#define OPAL_START_CPU			41
+#define	OPAL_START_CPU			41
 #define	OPAL_PCI_MAP_PE_DMA_WINDOW_REAL	45
 
 /* For OPAL_PCI_SET_PE */

Modified: projects/powernv/powerpc/powernv/opal_dev.c
==============================================================================
--- projects/powernv/powerpc/powernv/opal_dev.c	Sun Nov 15 18:56:58 2015	(r290871)
+++ projects/powernv/powerpc/powernv/opal_dev.c	Sun Nov 15 19:30:56 2015	(r290872)
@@ -37,6 +37,10 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/reboot.h>
 #include <sys/sysctl.h>
+#include <sys/endian.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
 
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
@@ -104,9 +108,19 @@ opaldev_attach(device_t dev)
 {
 	phandle_t child;
 	device_t cdev;
+	uint64_t junk;
+	int rv;
 	struct ofw_bus_devinfo *dinfo;
 
-	if (0 /* XXX NOT YET TEST FOR RTC */)
+	/* Test for RTC support and register clock if it works */
+	rv = opal_call(OPAL_RTC_READ, vtophys(&junk), vtophys(&junk));
+	do {
+		rv = opal_call(OPAL_RTC_READ, vtophys(&junk), vtophys(&junk));
+		if (rv == OPAL_BUSY_EVENT)
+			rv = opal_call(OPAL_POLL_EVENTS, 0);
+	} while (rv == OPAL_BUSY_EVENT);
+
+	if (rv == OPAL_SUCCESS)
 		clock_register(dev, 2000);
 	
 	EVENTHANDLER_REGISTER(shutdown_final, opal_shutdown, NULL,
@@ -134,13 +148,56 @@ opaldev_attach(device_t dev)
 }
 
 static int
-opal_gettime(device_t dev, struct timespec *ts) {
-	return (ENXIO);
+bcd2bin32(int bcd)
+{
+	int out = 0;
+
+	out += bcd2bin(bcd & 0xff);
+	out += 100*bcd2bin((bcd & 0x0000ff00) >> 8);
+	out += 10000*bcd2bin((bcd & 0x00ff0000) >> 16);
+	out += 1000000*bcd2bin((bcd & 0xffff0000) >> 24);
+
+	return (out);
+}
+
+static int
+opal_gettime(device_t dev, struct timespec *ts)
+{
+	int rv;
+	struct clocktime ct;
+	uint32_t ymd;
+	uint64_t hmsm;
+
+	do {
+		rv = opal_call(OPAL_RTC_READ, vtophys(&ymd), vtophys(&hmsm));
+		if (rv == OPAL_BUSY_EVENT) {
+			rv = opal_call(OPAL_POLL_EVENTS, 0);
+			pause("opalrtc", 1);
+		}
+	} while (rv == OPAL_BUSY_EVENT);
+
+	if (rv != OPAL_SUCCESS)
+		return (ENXIO);
+
+	hmsm = be64toh(hmsm);
+	ymd = be32toh(ymd);
+
+	ct.nsec	= bcd2bin32((hmsm & 0x000000ffffff0000) >> 16) * 1000;
+	ct.sec	= bcd2bin((hmsm & 0x0000ff0000000000) >> 40);
+	ct.min	= bcd2bin((hmsm & 0x00ff000000000000) >> 48);
+	ct.hour	= bcd2bin((hmsm & 0xff00000000000000) >> 56);
+
+	ct.day	= bcd2bin((ymd & 0x000000ff) >> 0);
+	ct.mon	= bcd2bin((ymd & 0x0000ff00) >> 8);
+	ct.year	= bcd2bin32((ymd & 0xffff0000) >> 16);
+	
+	return (clock_ct_to_ts(&ct, ts));
 }
 
 static int
 opal_settime(device_t dev, struct timespec *ts)
 {
+
 	return (0);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201511151930.tAFJUuX2069068>