diff options
author | andrew <andrew@FreeBSD.org> | 2010-07-22 23:23:39 +0000 |
---|---|---|
committer | andrew <andrew@FreeBSD.org> | 2010-07-22 23:23:39 +0000 |
commit | 1ac6286cc1262c7b3da9e7a6759f6bf6fbe447ad (patch) | |
tree | 38731bd871eb4133659535f9d90c1213a1c325f0 | |
parent | 621cb47cb7c730cb440fc3208c574c78ae05c003 (diff) | |
download | FreeBSD-src-1ac6286cc1262c7b3da9e7a6759f6bf6fbe447ad.zip FreeBSD-src-1ac6286cc1262c7b3da9e7a6759f6bf6fbe447ad.tar.gz |
Add the s3c24x0 real time clock driver
Approved by: imp (mentor)
-rw-r--r-- | sys/arm/s3c2xx0/files.s3c2xx0 | 1 | ||||
-rw-r--r-- | sys/arm/s3c2xx0/s3c24x0.c | 4 | ||||
-rw-r--r-- | sys/arm/s3c2xx0/s3c24x0_rtc.c | 162 | ||||
-rw-r--r-- | sys/arm/s3c2xx0/s3c24x0reg.h | 28 |
4 files changed, 194 insertions, 1 deletions
diff --git a/sys/arm/s3c2xx0/files.s3c2xx0 b/sys/arm/s3c2xx0/files.s3c2xx0 index 113f9dd..7a19c50 100644 --- a/sys/arm/s3c2xx0/files.s3c2xx0 +++ b/sys/arm/s3c2xx0/files.s3c2xx0 @@ -2,6 +2,7 @@ arm/arm/cpufunc_asm_arm9.S standard arm/arm/irq_dispatch.S standard arm/s3c2xx0/board_ln2410sbc.c optional board_ln2410sbc +arm/s3c2xx0/s3c24x0_rtc.c standard arm/s3c2xx0/s3c24x0_machdep.c standard arm/s3c2xx0/s3c24x0.c standard arm/s3c2xx0/s3c2xx0_space.c standard diff --git a/sys/arm/s3c2xx0/s3c24x0.c b/sys/arm/s3c2xx0/s3c24x0.c index c896bcf..fbcc42c 100644 --- a/sys/arm/s3c2xx0/s3c24x0.c +++ b/sys/arm/s3c2xx0/s3c24x0.c @@ -80,6 +80,10 @@ static struct { u_long count; } res[2]; } s3c24x0_children[] = { + { "rtc", 0, -1, { + { SYS_RES_IOPORT, S3C24X0_RTC_PA_BASE, S3C24X0_RTC_SIZE }, + { 0 }, + } }, { "timer", 0, -1, { { 0 }, } }, { "uart", 1, 0, { { SYS_RES_IRQ, S3C24X0_INT_UART0, 1 }, diff --git a/sys/arm/s3c2xx0/s3c24x0_rtc.c b/sys/arm/s3c2xx0/s3c24x0_rtc.c new file mode 100644 index 0000000..8845c44 --- /dev/null +++ b/sys/arm/s3c2xx0/s3c24x0_rtc.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2010 Andrew Turner + * 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. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/time.h> +#include <sys/clock.h> +#include <sys/resource.h> +#include <sys/systm.h> +#include <sys/rman.h> +#include <sys/kernel.h> +#include <sys/module.h> + +#include <machine/bus.h> + +#include <arm/s3c2xx0/s3c24x0reg.h> + +#include "clock_if.h" + +#define YEAR_BASE 2000 + +struct s3c2xx0_rtc_softc { + struct resource *mem_res; +}; + +static int +s3c2xx0_rtc_probe(device_t dev) +{ + + device_set_desc(dev, "Samsung Integrated RTC"); + return (0); +} + +static int +s3c2xx0_rtc_attach(device_t dev) +{ + struct s3c2xx0_rtc_softc *sc; + int error, rid; + + sc = device_get_softc(dev); + error = 0; + + rid = 0; + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, + RF_ACTIVE); + if (sc->mem_res == NULL) { + error = ENOMEM; + goto out; + } + + bus_write_1(sc->mem_res, RTC_RTCCON, RTCCON_RTCEN); + clock_register(dev, 1000000); + +out: + return (error); +} + +static int +s3c2xx0_rtc_gettime(device_t dev, struct timespec *ts) +{ + struct s3c2xx0_rtc_softc *sc; + struct clocktime ct; + +#define READ_TIME() do { \ + ct.year = YEAR_BASE + FROMBCD(bus_read_1(sc->mem_res, RTC_BCDYEAR)); \ + ct.mon = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDMON)); \ + ct.dow = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDDAY)); \ + ct.day = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDDATE)); \ + ct.hour = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDHOUR)); \ + ct.min = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDMIN)); \ + ct.sec = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDSEC)); \ +} while (0) + + sc = device_get_softc(dev); + + ct.nsec = 0; + READ_TIME(); + /* + * Check if we could have read incorrect values + * as the values could have changed. + */ + if (ct.sec == 0) { + READ_TIME(); + } + + ct.dow = -1; + +#undef READ_TIME + return (clock_ct_to_ts(&ct, ts)); +} + +static int +s3c2xx0_rtc_settime(device_t dev, struct timespec *ts) +{ + struct s3c2xx0_rtc_softc *sc; + struct clocktime ct; + + sc = device_get_softc(dev); + + /* Resolution: 1 sec */ + if (ts->tv_nsec >= 500000000) + ts->tv_sec++; + ts->tv_nsec = 0; + clock_ts_to_ct(ts, &ct); + + bus_write_1(sc->mem_res, RTC_BCDSEC, TOBCD(ct.sec)); + bus_write_1(sc->mem_res, RTC_BCDMIN, TOBCD(ct.min)); + bus_write_1(sc->mem_res, RTC_BCDHOUR, TOBCD(ct.hour)); + bus_write_1(sc->mem_res, RTC_BCDDATE, TOBCD(ct.day)); + bus_write_1(sc->mem_res, RTC_BCDDAY, TOBCD(ct.dow)); + bus_write_1(sc->mem_res, RTC_BCDMON, TOBCD(ct.mon)); + bus_write_1(sc->mem_res, RTC_BCDYEAR, TOBCD(ct.year - YEAR_BASE)); + + return (0); +} + +static device_method_t s3c2xx0_rtc_methods[] = { + DEVMETHOD(device_probe, s3c2xx0_rtc_probe), + DEVMETHOD(device_attach, s3c2xx0_rtc_attach), + + DEVMETHOD(clock_gettime, s3c2xx0_rtc_gettime), + DEVMETHOD(clock_settime, s3c2xx0_rtc_settime), + + { 0, 0 }, +}; + +static driver_t s3c2xx0_rtc_driver = { + "rtc", + s3c2xx0_rtc_methods, + sizeof(struct s3c2xx0_rtc_softc), +}; +static devclass_t s3c2xx0_rtc_devclass; + +DRIVER_MODULE(s3c2xx0_rtc, s3c24x0, s3c2xx0_rtc_driver, s3c2xx0_rtc_devclass, + 0, 0); + diff --git a/sys/arm/s3c2xx0/s3c24x0reg.h b/sys/arm/s3c2xx0/s3c24x0reg.h index 25bee39..1c18fa0 100644 --- a/sys/arm/s3c2xx0/s3c24x0reg.h +++ b/sys/arm/s3c2xx0/s3c24x0reg.h @@ -99,6 +99,9 @@ #define S3C24X0_IIS_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_IIS_PA_BASE) #define S3C24X0_GPIO_PA_BASE 0x56000000 #define S3C24X0_GPIO_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_GPIO_PA_BASE) +#define S3C24X0_RTC_PA_BASE 0x57000000 +#define S3C24X0_RTC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_RTC_PA_BASE) +#define S3C24X0_RTC_SIZE 0x8C #define S3C24X0_ADC_PA_BASE 0x58000000 #define S3C24X0_ADC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_ADC_PA_BASE) #define S3C24X0_SPI0_PA_BASE 0x59000000 @@ -642,7 +645,30 @@ #define ADCDAT_DATAMASK 0x3ff -/* RTC */ /* XXX */ +/* RTC */ +#define RTC_RTCCON 0x40 +#define RTCCON_RTCEN (1<<0) +#define RTCCON_CLKSEL (1<<1) +#define RTCCON_CNTSEL (1<<2) +#define RTCCON_CLKRST (1<<3) +#define RTC_TICNT0 0x44 +/* TICNT1 on 2440 */ +#define RTC_RTCALM 0x50 +#define RTC_ALMSEC 0x54 +#define RTC_ALMMIN 0x58 +#define RTC_ALMHOUR 0x5C +#define RTC_ALMDATE 0x60 +#define RTC_ALMMON 0x64 +#define RTC_ALMYEAR 0x68 +/* RTCRST on 2410 */ +#define RTC_BCDSEC 0x70 +#define RTC_BCDMIN 0x74 +#define RTC_BCDHOUR 0x78 +#define RTC_BCDDATE 0x7C +#define RTC_BCDDAY 0x80 +#define RTC_BCDMON 0x84 +#define RTC_BCDYEAR 0x88 + /* SPI */ #define S3C24X0_SPI_SIZE 0x20 |