From e1c912de869dab2244e47bf0799dcf7c8148b618 Mon Sep 17 00:00:00 2001 From: marius Date: Sat, 16 Jun 2007 23:17:23 +0000 Subject: - Flesh out the support for the EBus variant which actually is the RTC function of a National Semiconductor PC87317/PC97317. This consists of using the century register the same way Solaris does for compatibility reasons. Once there is a MD power(4) we'd also want to interface the APC (Advanced Power Control) functionality of the same chip function with it. - Use a macro for the device description and take advantage of ISA_PNP_PROBE() setting the device description. - Use the generated typedefs for the prototypes of the device interface functions. --- sys/sparc64/sparc64/rtc.c | 96 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 21 deletions(-) (limited to 'sys/sparc64') diff --git a/sys/sparc64/sparc64/rtc.c b/sys/sparc64/sparc64/rtc.c index fd988da..f018131 100644 --- a/sys/sparc64/sparc64/rtc.c +++ b/sys/sparc64/sparc64/rtc.c @@ -28,9 +28,10 @@ __FBSDID("$FreeBSD$"); /* - * The `rtc' device is a MC146818 compatible clock found on the ISA bus - * and EBus. The EBus version also has an interrupt property so it could - * be used to drive the statclock etc. + * The `rtc' device is a MC146818 compatible clock found on the ISA + * bus and EBus. The EBus variant actually is the Real-Time Clock + * function of a National Semiconductor PC87317/PC97317 which also + * provides Advanced Power Control functionality. */ #include "opt_isa.h" @@ -53,16 +54,30 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include "clock_if.h" +#define RTC_DESC "Real-Time Clock" + +#define RTC_READ mc146818_def_read +#define RTC_WRITE mc146818_def_write + +#define PC87317_COMMON MC_REGA_DV0 /* bank 0 */ +#define PC87317_RTC (MC_REGA_DV1 | MC_REGA_DV0) /* bank 1 */ +#define PC87317_RTC_CR 0x48 /* Century Register */ +#define PC87317_APC MC_REGA_DV2 /* bank 2 */ +#define PC87317_APC_CADDR 0x51 /* Century Address Register */ +#define PC87317_APC_CADDR_BANK0 0x00 /* locate CR in bank 0 */ +#define PC87317_APC_CADDR_BANK1 0x80 /* locate CR in bank 1 */ + static devclass_t rtc_devclass; -static int rtc_attach(device_t dev); -static int rtc_ebus_probe(device_t dev); +static device_attach_t rtc_attach; +static device_probe_t rtc_ebus_probe; #ifdef DEV_ISA -static int rtc_isa_probe(device_t dev); +static device_probe_t rtc_isa_probe; #endif static device_method_t rtc_ebus_methods[] = { @@ -107,12 +122,15 @@ static driver_t rtc_isa_driver = { DRIVER_MODULE(rtc, isa, rtc_isa_driver, rtc_devclass, 0, 0); #endif +static u_int pc87317_getcent(device_t); +static void pc87317_setcent(device_t, u_int); + static int rtc_ebus_probe(device_t dev) { - + if (strcmp(ofw_bus_get_name(dev), "rtc") == 0) { - device_set_desc(dev, "Real Time Clock"); + device_set_desc(dev, RTC_DESC); return (0); } @@ -121,7 +139,7 @@ rtc_ebus_probe(device_t dev) #ifdef DEV_ISA static struct isa_pnp_id rtc_isa_ids[] = { - { 0x000bd041, "AT realtime clock" }, /* PNP0B00 */ + { 0x000bd041, RTC_DESC }, /* PNP0B00 */ { 0 } }; @@ -129,10 +147,8 @@ static int rtc_isa_probe(device_t dev) { - if (ISA_PNP_PROBE(device_get_parent(dev), dev, rtc_isa_ids) == 0) { - device_set_desc(dev, "Real Time Clock"); + if (ISA_PNP_PROBE(device_get_parent(dev), dev, rtc_isa_ids) == 0) return (0); - } return (ENXIO); } @@ -144,19 +160,19 @@ rtc_attach(device_t dev) struct timespec ts; struct mc146818_softc *sc; struct resource *res; - int error, rid, rtype; + int ebus, error, rid; sc = device_get_softc(dev); mtx_init(&sc->sc_mtx, "rtc_mtx", NULL, MTX_SPIN); - if (strcmp(device_get_name(device_get_parent(dev)), "isa") == 0) - rtype = SYS_RES_IOPORT; - else - rtype = SYS_RES_MEMORY; + ebus = 0; + if (strcmp(device_get_name(device_get_parent(dev)), "ebus") == 0) + ebus = 1; rid = 0; - res = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE); + res = bus_alloc_resource_any(dev, ebus ? SYS_RES_MEMORY : + SYS_RES_IOPORT, &rid, RF_ACTIVE); if (res == NULL) { device_printf(dev, "cannot allocate resources\n"); error = ENXIO; @@ -165,10 +181,27 @@ rtc_attach(device_t dev) sc->sc_bst = rman_get_bustag(res); sc->sc_bsh = rman_get_bushandle(res); + sc->sc_mcread = RTC_READ; + sc->sc_mcwrite = RTC_WRITE; /* The TOD clock year 0 is 0. */ sc->sc_year0 = 0; - /* Use default register read/write and century get/set functions. */ + /* + * For ISA use the default century get/set functions, for EBus we + * provide our own versions. + */ sc->sc_flag = MC146818_NO_CENT_ADJUST; + if (ebus) { + /* + * Make sure the CR is at the default location (also used + * by Solaris). + */ + RTC_WRITE(dev, MC_REGA, PC87317_APC); + RTC_WRITE(dev, PC87317_APC_CADDR, PC87317_APC_CADDR_BANK1 | + PC87317_RTC_CR); + RTC_WRITE(dev, MC_REGA, PC87317_COMMON); + sc->sc_getcent = pc87317_getcent; + sc->sc_setcent = pc87317_setcent; + } if ((error = mc146818_attach(dev)) != 0) { device_printf(dev, "cannot attach time of day clock\n"); goto fail_res; @@ -178,14 +211,35 @@ rtc_attach(device_t dev) mc146818_gettime(dev, &ts); device_printf(dev, "current time: %ld.%09ld\n", (long)ts.tv_sec, ts.tv_nsec); - } + } return (0); fail_res: - bus_release_resource(dev, rtype, rid, res); + bus_release_resource(dev, ebus ? SYS_RES_MEMORY : SYS_RES_IOPORT, rid, + res); fail_mtx: mtx_destroy(&sc->sc_mtx); return (error); } + +static u_int +pc87317_getcent(device_t dev) +{ + u_int cent; + + RTC_WRITE(dev, MC_REGA, PC87317_RTC); + cent = RTC_READ(dev, PC87317_RTC_CR); + RTC_WRITE(dev, MC_REGA, PC87317_COMMON); + return (cent); +} + +static void +pc87317_setcent(device_t dev, u_int cent) +{ + + RTC_WRITE(dev, MC_REGA, PC87317_RTC); + RTC_WRITE(dev, PC87317_RTC_CR, cent); + RTC_WRITE(dev, MC_REGA, PC87317_COMMON); +} -- cgit v1.1