xref: /freebsd/sys/powerpc/pseries/rtas_dev.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
17a8d25c0SNathan Whitehorn /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
371e3c308SPedro F. Giffuni  *
47a8d25c0SNathan Whitehorn  * Copyright (c) 2011 Nathan Whitehorn
57a8d25c0SNathan Whitehorn  * All rights reserved.
67a8d25c0SNathan Whitehorn  *
77a8d25c0SNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
87a8d25c0SNathan Whitehorn  * modification, are permitted provided that the following conditions
97a8d25c0SNathan Whitehorn  * are met:
107a8d25c0SNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
117a8d25c0SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
127a8d25c0SNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
137a8d25c0SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
147a8d25c0SNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
157a8d25c0SNathan Whitehorn  *
167a8d25c0SNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
177a8d25c0SNathan Whitehorn  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
187a8d25c0SNathan Whitehorn  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
197a8d25c0SNathan Whitehorn  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
207a8d25c0SNathan Whitehorn  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
217a8d25c0SNathan Whitehorn  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
227a8d25c0SNathan Whitehorn  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
237a8d25c0SNathan Whitehorn  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
247a8d25c0SNathan Whitehorn  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
257a8d25c0SNathan Whitehorn  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
267a8d25c0SNathan Whitehorn  * SUCH DAMAGE.
277a8d25c0SNathan Whitehorn  */
287a8d25c0SNathan Whitehorn 
297a8d25c0SNathan Whitehorn #include <sys/param.h>
307a8d25c0SNathan Whitehorn #include <sys/systm.h>
317a8d25c0SNathan Whitehorn #include <sys/module.h>
327a8d25c0SNathan Whitehorn #include <sys/bus.h>
337a8d25c0SNathan Whitehorn #include <sys/conf.h>
347a8d25c0SNathan Whitehorn #include <sys/clock.h>
357a8d25c0SNathan Whitehorn #include <sys/cpu.h>
36e2e050c8SConrad Meyer #include <sys/eventhandler.h>
377a8d25c0SNathan Whitehorn #include <sys/kernel.h>
387a8d25c0SNathan Whitehorn #include <sys/reboot.h>
397a8d25c0SNathan Whitehorn #include <sys/sysctl.h>
407a8d25c0SNathan Whitehorn 
417a8d25c0SNathan Whitehorn #include <dev/ofw/ofw_bus.h>
427a8d25c0SNathan Whitehorn #include <dev/ofw/openfirm.h>
437a8d25c0SNathan Whitehorn 
447a8d25c0SNathan Whitehorn #include <machine/rtas.h>
457a8d25c0SNathan Whitehorn 
467a8d25c0SNathan Whitehorn #include "clock_if.h"
477a8d25c0SNathan Whitehorn 
487a8d25c0SNathan Whitehorn static int	rtasdev_probe(device_t);
497a8d25c0SNathan Whitehorn static int	rtasdev_attach(device_t);
507a8d25c0SNathan Whitehorn /* clock interface */
517a8d25c0SNathan Whitehorn static int	rtas_gettime(device_t dev, struct timespec *ts);
527a8d25c0SNathan Whitehorn static int	rtas_settime(device_t dev, struct timespec *ts);
537a8d25c0SNathan Whitehorn 
547a8d25c0SNathan Whitehorn static void	rtas_shutdown(void *arg, int howto);
557a8d25c0SNathan Whitehorn 
567a8d25c0SNathan Whitehorn static device_method_t  rtasdev_methods[] = {
577a8d25c0SNathan Whitehorn 	/* Device interface */
587a8d25c0SNathan Whitehorn 	DEVMETHOD(device_probe,		rtasdev_probe),
597a8d25c0SNathan Whitehorn 	DEVMETHOD(device_attach,	rtasdev_attach),
607a8d25c0SNathan Whitehorn 
617a8d25c0SNathan Whitehorn 	/* clock interface */
627a8d25c0SNathan Whitehorn 	DEVMETHOD(clock_gettime,	rtas_gettime),
637a8d25c0SNathan Whitehorn 	DEVMETHOD(clock_settime,	rtas_settime),
647a8d25c0SNathan Whitehorn 
657a8d25c0SNathan Whitehorn 	{ 0, 0 },
667a8d25c0SNathan Whitehorn };
677a8d25c0SNathan Whitehorn 
687a8d25c0SNathan Whitehorn static driver_t rtasdev_driver = {
697a8d25c0SNathan Whitehorn 	"rtas",
707a8d25c0SNathan Whitehorn 	rtasdev_methods,
717a8d25c0SNathan Whitehorn 	0
727a8d25c0SNathan Whitehorn };
737a8d25c0SNathan Whitehorn 
749b9a5327SJohn Baldwin DRIVER_MODULE(rtasdev, ofwbus, rtasdev_driver, 0, 0);
757a8d25c0SNathan Whitehorn 
767a8d25c0SNathan Whitehorn static int
rtasdev_probe(device_t dev)777a8d25c0SNathan Whitehorn rtasdev_probe(device_t dev)
787a8d25c0SNathan Whitehorn {
797a8d25c0SNathan Whitehorn 	const char *name = ofw_bus_get_name(dev);
807a8d25c0SNathan Whitehorn 
817a8d25c0SNathan Whitehorn 	if (strcmp(name, "rtas") != 0)
827a8d25c0SNathan Whitehorn 		return (ENXIO);
837a8d25c0SNathan Whitehorn 	if (!rtas_exists())
847a8d25c0SNathan Whitehorn 		return (ENXIO);
857a8d25c0SNathan Whitehorn 
867a8d25c0SNathan Whitehorn 	device_set_desc(dev, "Run-Time Abstraction Services");
877a8d25c0SNathan Whitehorn 	return (0);
887a8d25c0SNathan Whitehorn }
897a8d25c0SNathan Whitehorn 
907a8d25c0SNathan Whitehorn static int
rtasdev_attach(device_t dev)917a8d25c0SNathan Whitehorn rtasdev_attach(device_t dev)
927a8d25c0SNathan Whitehorn {
937a8d25c0SNathan Whitehorn 	if (rtas_token_lookup("get-time-of-day") != -1)
947a8d25c0SNathan Whitehorn 		clock_register(dev, 2000);
957a8d25c0SNathan Whitehorn 
967a8d25c0SNathan Whitehorn 	EVENTHANDLER_REGISTER(shutdown_final, rtas_shutdown, NULL,
977a8d25c0SNathan Whitehorn 	    SHUTDOWN_PRI_LAST);
987a8d25c0SNathan Whitehorn 
997a8d25c0SNathan Whitehorn 	return (0);
1007a8d25c0SNathan Whitehorn }
1017a8d25c0SNathan Whitehorn 
1027a8d25c0SNathan Whitehorn static int
rtas_gettime(device_t dev,struct timespec * ts)1037a8d25c0SNathan Whitehorn rtas_gettime(device_t dev, struct timespec *ts) {
1047a8d25c0SNathan Whitehorn 	struct clocktime ct;
1057a8d25c0SNathan Whitehorn 	cell_t tod[8];
1067a8d25c0SNathan Whitehorn 	cell_t token;
1077a8d25c0SNathan Whitehorn 	int error;
1087a8d25c0SNathan Whitehorn 
1097a8d25c0SNathan Whitehorn 	token = rtas_token_lookup("get-time-of-day");
1107a8d25c0SNathan Whitehorn 	if (token == -1)
1117a8d25c0SNathan Whitehorn 		return (ENXIO);
1127a8d25c0SNathan Whitehorn 	error = rtas_call_method(token, 0, 8, &tod[0], &tod[1], &tod[2],
1137a8d25c0SNathan Whitehorn 	    &tod[3], &tod[4], &tod[5], &tod[6], &tod[7]);
1147a8d25c0SNathan Whitehorn 	if (error < 0)
1157a8d25c0SNathan Whitehorn 		return (ENXIO);
1167a8d25c0SNathan Whitehorn 	if (tod[0] != 0)
1177a8d25c0SNathan Whitehorn 		return ((tod[0] == -1) ? ENXIO : EAGAIN);
1187a8d25c0SNathan Whitehorn 
1197a8d25c0SNathan Whitehorn 	ct.year = tod[1];
1207a8d25c0SNathan Whitehorn 	ct.mon  = tod[2];
1217a8d25c0SNathan Whitehorn 	ct.day  = tod[3];
1227a8d25c0SNathan Whitehorn 	ct.hour = tod[4];
1237a8d25c0SNathan Whitehorn 	ct.min  = tod[5];
1247a8d25c0SNathan Whitehorn 	ct.sec  = tod[6];
1257a8d25c0SNathan Whitehorn 	ct.nsec = tod[7];
1267a8d25c0SNathan Whitehorn 
1277a8d25c0SNathan Whitehorn 	return (clock_ct_to_ts(&ct, ts));
1287a8d25c0SNathan Whitehorn }
1297a8d25c0SNathan Whitehorn 
1307a8d25c0SNathan Whitehorn static int
rtas_settime(device_t dev,struct timespec * ts)1317a8d25c0SNathan Whitehorn rtas_settime(device_t dev, struct timespec *ts)
1327a8d25c0SNathan Whitehorn {
1337a8d25c0SNathan Whitehorn 	struct clocktime ct;
1347a8d25c0SNathan Whitehorn 	cell_t token, status;
1357a8d25c0SNathan Whitehorn 	int error;
1367a8d25c0SNathan Whitehorn 
1377a8d25c0SNathan Whitehorn 	token = rtas_token_lookup("set-time-of-day");
1387a8d25c0SNathan Whitehorn 	if (token == -1)
1397a8d25c0SNathan Whitehorn 		return (ENXIO);
1407a8d25c0SNathan Whitehorn 
1417a8d25c0SNathan Whitehorn 	clock_ts_to_ct(ts, &ct);
1427a8d25c0SNathan Whitehorn 	error = rtas_call_method(token, 7, 1, ct.year, ct.mon, ct.day, ct.hour,
1437a8d25c0SNathan Whitehorn 	    ct.min, ct.sec, ct.nsec, &status);
1447a8d25c0SNathan Whitehorn 	if (error < 0)
1457a8d25c0SNathan Whitehorn 		return (ENXIO);
1467a8d25c0SNathan Whitehorn 	if (status != 0)
1477a8d25c0SNathan Whitehorn 		return (((int)status < 0) ? ENXIO : EAGAIN);
1487a8d25c0SNathan Whitehorn 
1497a8d25c0SNathan Whitehorn 	return (0);
1507a8d25c0SNathan Whitehorn }
1517a8d25c0SNathan Whitehorn 
1527a8d25c0SNathan Whitehorn static void
rtas_shutdown(void * arg,int howto)1537a8d25c0SNathan Whitehorn rtas_shutdown(void *arg, int howto)
1547a8d25c0SNathan Whitehorn {
1557a8d25c0SNathan Whitehorn 	cell_t token, status;
1567a8d25c0SNathan Whitehorn 
157*41e26e82SMitchell Horne 	if ((howto & RB_POWEROFF) != 0) {
1587a8d25c0SNathan Whitehorn 		token = rtas_token_lookup("power-off");
1597a8d25c0SNathan Whitehorn 		if (token == -1)
1607a8d25c0SNathan Whitehorn 			return;
1617a8d25c0SNathan Whitehorn 
1627a8d25c0SNathan Whitehorn 		rtas_call_method(token, 2, 1, 0, 0, &status);
163*41e26e82SMitchell Horne 	} else if ((howto & RB_HALT) == 0) {
1647a8d25c0SNathan Whitehorn 		token = rtas_token_lookup("system-reboot");
1657a8d25c0SNathan Whitehorn 		if (token == -1)
1667a8d25c0SNathan Whitehorn 			return;
1677a8d25c0SNathan Whitehorn 
1687a8d25c0SNathan Whitehorn 		rtas_call_method(token, 0, 1, &status);
1697a8d25c0SNathan Whitehorn 	}
1707a8d25c0SNathan Whitehorn }
171