svn commit: r329702 - head/sys/powerpc/powernv

Wojciech Macek wma at FreeBSD.org
Wed Feb 21 08:13:18 UTC 2018


Author: wma
Date: Wed Feb 21 08:13:17 2018
New Revision: 329702
URL: https://svnweb.freebsd.org/changeset/base/329702

Log:
  PowerNV: add missing RTC_WRITE support
  
  Add function which can store RTC values to OPAL.
  
  Submitted by:          Wojciech Macek <wma at semihalf.org>
  Obtained from:         Semihalf
  Sponsored by:          IBM, QCM Technologies

Modified:
  head/sys/powerpc/powernv/opal_dev.c

Modified: head/sys/powerpc/powernv/opal_dev.c
==============================================================================
--- head/sys/powerpc/powernv/opal_dev.c	Wed Feb 21 08:05:56 2018	(r329701)
+++ head/sys/powerpc/powernv/opal_dev.c	Wed Feb 21 08:13:17 2018	(r329702)
@@ -191,6 +191,26 @@ bcd2bin32(int bcd)
 }
 
 static int
+bin2bcd32(int bin)
+{
+	int out = 0;
+	int tmp;
+
+	tmp = bin % 100;
+	out += bin2bcd(tmp) * 1;
+	bin = bin / 100;
+
+	tmp = bin % 100;
+	out += bin2bcd(tmp) * 100;
+	bin = bin / 100;
+
+	tmp = bin % 100;
+	out += bin2bcd(tmp) * 10000;
+
+	return (out);
+}
+
+static int
 opal_gettime(device_t dev, struct timespec *ts)
 {
 	int rv;
@@ -220,13 +240,42 @@ opal_gettime(device_t dev, struct timespec *ts)
 	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)
 {
+	int rv;
+	struct clocktime ct;
+	uint32_t ymd = 0;
+	uint64_t hmsm = 0;
+
+	clock_ts_to_ct(ts, &ct);
+
+	ymd |= (uint32_t)bin2bcd(ct.day);
+	ymd |= ((uint32_t)bin2bcd(ct.mon) << 8);
+	ymd |= ((uint32_t)bin2bcd32(ct.year) << 16);
+
+	hmsm |= ((uint64_t)bin2bcd32(ct.nsec/1000) << 16);
+	hmsm |= ((uint64_t)bin2bcd(ct.sec) << 40);
+	hmsm |= ((uint64_t)bin2bcd(ct.min) << 48);
+	hmsm |= ((uint64_t)bin2bcd(ct.hour) << 56);
+
+	hmsm = htobe64(hmsm);
+	ymd = htobe32(ymd);
+
+	do {
+		rv = opal_call(OPAL_RTC_WRITE, 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);
 
 	return (0);
 }


More information about the svn-src-head mailing list