From f5b890d0980e374ac4902d62984d585597c1b84a Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 8 Jun 2019 09:58:24 -0600 Subject: [PATCH] Squashed commit of the following: arch/z80/src/ez80: Clean-up RTC driver; get a clean compilation. Still untested. arch/z80/src/ez80: This brings the RTC to code complete, but does not yet compile. arch/z80/src/ez80/ez80_rtc.c: Bring in badly ported RTC driver from STM32F4. Little more than naming changing at this point not even ready to attempt comilation arch/z80/src/ez80: Add RTC driver. Initial commit is just the STMF4 RTC driver with name changes. --- arch/z80/src/common/up_initialize.c | 8 +- arch/z80/src/common/up_internal.h | 4 + arch/z80/src/ez80/Kconfig | 25 +- arch/z80/src/ez80/Make.defs | 4 + arch/z80/src/ez80/ez80_rtc.c | 801 ++++++++++++++++++++++++++++ arch/z80/src/ez80/ez80_rtc.h | 208 ++++++++ 6 files changed, 1048 insertions(+), 2 deletions(-) create mode 100644 arch/z80/src/ez80/ez80_rtc.c create mode 100644 arch/z80/src/ez80/ez80_rtc.h diff --git a/arch/z80/src/common/up_initialize.c b/arch/z80/src/common/up_initialize.c index eb286638ff..83501acbc2 100644 --- a/arch/z80/src/common/up_initialize.c +++ b/arch/z80/src/common/up_initialize.c @@ -12,7 +12,7 @@ * 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 + * the documentation and/or otherr materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software @@ -99,6 +99,12 @@ void up_initialize(void) up_irqinitialize(); +#ifdef CONFIG_RTC_ALARM + /* Enable RTC alarm interrupts */ + + ez80_rtc_irqinitialize(); +#endif + #if !defined(CONFIG_SUPPRESS_INTERRUPTS) && !defined(CONFIG_SUPPRESS_TIMER_INTS) /* Initialize the system timer interrupt */ diff --git a/arch/z80/src/common/up_internal.h b/arch/z80/src/common/up_internal.h index 59e71a51f7..8c18f8e930 100644 --- a/arch/z80/src/common/up_internal.h +++ b/arch/z80/src/common/up_internal.h @@ -116,6 +116,10 @@ extern "C" void up_irqinitialize(void); +#ifdef CONFIG_RTC_ALARM +void ez80_rtc_irqinitialize(void); +#endif + #ifdef USE_LOWSERIALINIT void up_lowserialinit(void); #endif diff --git a/arch/z80/src/ez80/Kconfig b/arch/z80/src/ez80/Kconfig index d8bee2483d..fe99f5a7b9 100644 --- a/arch/z80/src/ez80/Kconfig +++ b/arch/z80/src/ez80/Kconfig @@ -30,6 +30,13 @@ config EZ80_SPI bool "SPI" default n +config EZ80_RTC + bool "RTC" + default n + select RTC + select RTC_DATETIME + select TIME_EXTENDED + config EZ80_EMAC bool "Ethernet MAC" default n @@ -38,7 +45,23 @@ config EZ80_EMAC ---help--- Enables support for ez80 EMAC driver. -endmenu +endmenu # ez80 Peripheral Support + +config EZ80_RTC_32KHZ + bool "32KHz crystal present" + default y + depends on EZ80_RTC + ---help--- + If there is no 32Hz crystal, the RTC will fall back to use the line + frequency. + +config EZ80_RTC_LINEFREQ50 + bool "50Hz line frequency" + default n + depends on EZ80_RTC && !EZ80_RTC_32KHZ + ---help--- + If there is no 32Hz crystal, the RTC will fall back to use the line + frequency, either 50 or 60Hz. # The ZiLOG ZDS-II Windows toolchain is the only toolchain available for # the ez80. diff --git a/arch/z80/src/ez80/Make.defs b/arch/z80/src/ez80/Make.defs index 36e69970a4..fb197236c2 100644 --- a/arch/z80/src/ez80/Make.defs +++ b/arch/z80/src/ez80/Make.defs @@ -63,6 +63,10 @@ ifeq ($(CONFIG_EZ80_SPI),y) CHIP_CSRCS += ez80_spi.c endif +ifeq ($(CONFIG_EZ80_RTC),y) +CHIP_CSRCS += ez80_rtc.c +endif + ifeq ($(CONFIG_ARCH_CHIP_EZ80F91),y) ifeq ($(CONFIG_EZ80_EMAC),y) CHIP_CSRCS += ez80_emac.c diff --git a/arch/z80/src/ez80/ez80_rtc.c b/arch/z80/src/ez80/ez80_rtc.c new file mode 100644 index 0000000000..02508bfa46 --- /dev/null +++ b/arch/z80/src/ez80/ez80_rtc.c @@ -0,0 +1,801 @@ +/**************************************************************************** + * arch/z80/src/ez80/ez80_rtc.c + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT OWNER 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "chip.h" +#include "up_arch.h" +#include "ez80_rtc.h" + +#include + +#ifdef CONFIG_EZ80_RTC + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_RTC_DATETIME +# error "CONFIG_RTC_DATETIME must be set to use this driver" +#endif + +#ifdef CONFIG_RTC_HIRES +# error "CONFIG_RTC_HIRES must NOT be set with this driver" +#endif + +/* Constants ****************************************************************/ + +#define SYNCHRO_TIMEOUT (0x00020000) +#define INITMODE_TIMEOUT (0x00010000) + +/* Proxy definitions to make the same code work for all the EZ80 series ****/ + +# define EZ80_RCC_XXX EZ80_RCC_BDCR +# define RCC_XXX_YYYRST RCC_BDCR_BDRST +# define RCC_XXX_RTCEN RCC_BDCR_RTCEN +# define RCC_XXX_RTCSEL_MASK RCC_BDCR_RTCSEL_MASK +# define RCC_XXX_RTCSEL_LSE RCC_BDCR_RTCSEL_LSE +# define RCC_XXX_RTCSEL_LSI RCC_BDCR_RTCSEL_LSI +# define RCC_XXX_RTCSEL_HSE RCC_BDCR_RTCSEL_HSE + +/* Time conversions */ + +#define MINUTES_IN_HOUR 60 +#define HOURS_IN_DAY 24 + +#define hours_add(parm_hrs) \ + time->tm_hour += parm_hrs;\ + if ((HOURS_IN_DAY-1) < (time->tm_hour))\ + {\ + time->tm_hour = (parm_hrs - HOURS_IN_DAY);\ + } + +#define RTC_ALRMR_DIS_MASK (RTC_ALRMR_MSK4 | RTC_ALRMR_MSK3 | \ + RTC_ALRMR_MSK2 | RTC_ALRMR_MSK1) +#define RTC_ALRMR_DIS_DATE_MASK (RTC_ALRMR_MSK4) +#define RTC_ALRMR_ENABLE (0) + +/**************************************************************************** + * Private Types + *****************************************************************************/ + +/* Raw time from the RTC. All are binary. */ + +struct rtc_timeregs_s +{ + uint8_t sec; /* Seconds Range 0-59 */ + uint8_t min; /* Minutes Range 0-59 */ + uint8_t hrs; /* Hours Range 0-23 */ + uint8_t dow; /* Day of week Range 1-7 */ + uint8_t dom; /* Day of month Range 1-31 */ + uint8_t mon; /* Month Range 1-12 */ + uint8_t yr; /* Year Range 0-99 */ + uint8_t cen; /* Century Range 0-99 */ +}; + +/* Alarm time from the RTC. All are BCD encoded. */ + +struct rtc_almregs_s +{ + uint8_t sec; /* Seconds */ + uint8_t min; /* Minutes */ + uint8_t hrs; /* Hours */ + uint8_t dow; /* Day of week */ +}; + +#ifdef CONFIG_RTC_ALARM +struct alm_cbinfo_s +{ + volatile alm_callback_t ac_cb; /* Client callback function */ + volatile FAR void *ac_arg; /* Argument to pass with the callback function */ +}; +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Interrupt handlers attached to the ALARM EXTI */ + +static xcpt_t g_alarm_callback; +static void *g_callback_arg; + +#ifdef CONFIG_RTC_ALARM +/* Callback to use when an EXTI is activated */ + +static struct alm_cbinfo_s g_alarmcb; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* g_rtc_enabled is set true after the RTC has successfully initialized */ + +volatile bool g_rtc_enabled = false; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Debug */ + +static void rtc_dumpregs(FAR const char *msg); +static void rtc_dumptime(FAR const struct tm *tp, FAR const char *msg); + +/* Register access */ + +static void rtc_unlock(void); +static void rtc_lock(void); + +static void get_raw_time(struct rtc_timeregs_s *rtcregs); +static void set_raw_time(const struct rtc_timeregs_s *rtcregs); + +#ifdef CONFIG_RTC_ALARM +static void get_raw_alarm(struct rtc_timeregs_s *almregs); +static void set_raw_alarm(const struct rtc_timeregs_s *almregs); +static int ez80_alarm_interrupt(int irq, void *context, void *arg); +static int ez80_rtc_getalarmdatetime(const struct rtc_almregs_s almregs + FAR struct tm *tp); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtc_dumpregs + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_RTC_INFO +static void rtc_dumpregs(FAR const char *msg) +{ + int rtc_state; + + rtcinfo("%s:\n", msg); + rtcinfo(" SEC: %02x\n", inp(EZ80_RTC_SEC)); + rtcinfo(" MIN: %02x\n", inp(EZ80_RTC_MIN)); + rtcinfo(" HRS: %02x\n", inp(EZ80_RTC_HRS)); + rtcinfo(" DOW: %02x\n", inp(EZ80_RTC_DOW)); + rtcinfo(" DOM: %02x\n", inp(EZ80_RTC_DOM)); + rtcinfo(" MON: %02x\n", inp(EZ80_RTC_MON)); + rtcinfo(" YR: %02x\n", inp(EZ80_RTC_YR)); + rtcinfo(" CEN: %02x\n", inp(EZ80_RTC_CEN)); + rtcinfo(" ASEC: %02x\n", inp(EZ80_RTC_ASEC)); + rtcinfo(" AMIN: %02x\n", inp(EZ80_RTC_AMIN)); + rtcinfo(" AHRS: %02x\n", inp(EZ80_RTC_AHRS)); + rtcinfo(" ADOW: %02x\n", inp(EZ80_RTC_ADOW)); + rtcinfo(" ACTRL: %02x\n", inp(EZ80_RTC_ACTRL)); + rtcinfo(" CTRL: %02x\n", inp(EZ80_RTC_CTRL)); +} +#else +# define rtc_dumpregs(msg) +#endif + +/**************************************************************************** + * Name: rtc_dumptime + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_RTC_INFO +static void rtc_dumptime(FAR const struct tm *tp, FAR const char *msg) +{ + rtcinfo("%s:\n", msg); + rtcinfo(" tm_sec: %08x\n", tp->tm_sec); + rtcinfo(" tm_min: %08x\n", tp->tm_min); + rtcinfo(" tm_hour: %08x\n", tp->tm_hour); + rtcinfo(" tm_mday: %08x\n", tp->tm_mday); + rtcinfo(" tm_mon: %08x\n", tp->tm_mon); + rtcinfo(" tm_year: %08x\n", tp->tm_year); +} +#else +# define rtc_dumptime(tp, msg) +#endif + +/**************************************************************************** + * Name: rtc_unlock + * + * Description: + * Disable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void rtc_unlock(void) +{ + uint8_t regval; + + regval = inp(EZ80_RTC_CTRL); + regval |= EZ80_RTC_UNLOCK; + outp(EZ80_RTC_CTRL,regval); +} + +/**************************************************************************** + * Name: rtc_lock + * + * Description: + * Enable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void rtc_lock(void) +{ + uint8_t regval; + + regval = inp(EZ80_RTC_CTRL); + regval &= ~EZ80_RTC_UNLOCK; + outp(EZ80_RTC_CTRL,regval); +} + +/**************************************************************************** + * Name: get_raw_time + * + * Description: + * Read all of the RTC time registers + * + * Input Parameters: + * rtcregs - Location to return the raw RTC time registers + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void get_raw_time(struct rtc_timeregs_s *rtcregs) +{ + rtcregs->sec = inp(EZ80_RTC_SEC); + rtcregs->min = inp(EZ80_RTC_MIN); + rtcregs->hrs = inp(EZ80_RTC_HRS); + rtcregs->dow = inp(EZ80_RTC_DOW); + rtcregs->dom = inp(EZ80_RTC_DOM); + rtcregs->mon = inp(EZ80_RTC_MON); + rtcregs->yr = inp(EZ80_RTC_YR); + rtcregs->cen = inp(EZ80_RTC_CEN); +} + +/**************************************************************************** + * Name: set_raw_time + * + * Description: + * Write all of the RTC time registers + * + * Input Parameters: + * almregs - New RTC register values + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void set_raw_time(const struct rtc_timeregs_s *rtcregs) +{ + rtc_unlock(); + outp(EZ80_RTC_SEC, rtcregs->sec); + outp(EZ80_RTC_MIN, rtcregs->min); + outp(EZ80_RTC_HRS, rtcregs->hrs); + outp(EZ80_RTC_DOW, rtcregs->dow); + outp(EZ80_RTC_DOM, rtcregs->dom); + outp(EZ80_RTC_MON, rtcregs->mon); + outp(EZ80_RTC_YR, rtcregs->yr); + outp(EZ80_RTC_CEN, rtcregs->cen); + rtc_unlock(); +} + +/**************************************************************************** + * Name: get_raw_alarm + * + * Description: + * Read all of the RTC alarm registers + * + * Input Parameters: + * almregs - Location to return the raw RTC alarm registers + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void get_raw_alarm(struct rtc_timeregs_s *almregs) +{ + almregs->sec = inp(EZ80_RTC_ASEC); + almregs->min = inp(EZ80_RTC_AMIN); + almregs->hrs = inp(EZ80_RTC_AHRS); + almregs->dow = inp(EZ80_RTC_ADOW); +} + +/**************************************************************************** + * Name: set_raw_alarm + * + * Description: + * Write all of the RTC alarm registers + * + * Input Parameters: + * almregs - New RTC register values + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void set_raw_alarm(const struct rtc_timeregs_s *almregs) +{ + rtc_unlock(); + outp(EZ80_RTC_ASEC, almregs->sec); + outp(EZ80_RTC_AMIN, almregs->min); + outp(EZ80_RTC_AHRS, almregs->hrs); + outp(EZ80_RTC_ADOW, almregs->dow); + rtc_unlock(); +} + +/**************************************************************************** + * Name: ez80_alarm_interrupt + * + * Description: + * RTC ALARM interrupt service routine through the EXTI line + * + * Input Parameters: + * irq - The IRQ number that generated the interrupt + * context - Architecture specific register save information. + * + * Returned Value: + * Zero (OK) on success; A negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static int ez80_alarm_interrupt(int irq, void *context, void *arg) +{ + uint_t regval; + + /* Verify that the alarm iinterrupt is pending */ + + regval = inp(EZ80_RTC_CTRL); + if ((regval & EZ80_RTC_ALARM) != 0) + { + /* Disable the alarm and disable the alarm interrupt */ + + rtc_unlock(); + outp(EZ80_RTC_ACTRL, 0); + + regval = inp(EZ80_RTC_CTRL); + regval &= ~EZ80_RTC_INTEN; + outp(EZ80_RTC_CTRL, regval); + rtc_lock(); + + up_irq_disble(EZ80_RTC_IRQ); + + /* Perform the alarm callback */ + + cb = g_alarmcb.ac_cb; + cb_arg = (FAR void *)g_alarmcb.ac_arg; + + g_alarmcb.ac_cb = NULL; + g_alarmcb.ac_arg = NULL; + + cb(cb_arg); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: ez80_rtc_getalarmdatetime + * + * Description: + * Get the current date and time for a RTC alarm. + * + * Input Parameters: + * reg - RTC alarm register + * tp - The location to return the high resolution time value. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static int ez80_rtc_getalarmdatetime(const struct rtc_almregs_s almregs + FAR struct tm *tp) +{ + uint32_t data, tmp; + + DEBUGASSERT(tp != NULL); + + /* Sample the data time register. */ + + data = inp(reg); + + /* Convert the RTC time to fields in struct tm format. All of the EZ80 + * ranges of values correspond between struct tm and the time register. + */ + + tp->tm_sec = xxx(tmp); + tp->tm_min = xxx(tmp); + tp->tm_hour = xxx(tmp); + tp->tm_mday = xxx(tmp); + + return OK; +} +#endif + +/**************************************************************************** + * Name: up_rtc_initialize + * + * Description: + * Initialize the hardware RTC per the selected configuration. This + * function is called once during the OS initialization sequence + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int up_rtc_initialize(void) +{ + uint8_t regval; + + /* Some boards do not have the external 32khz oscillator installed, + * for those boards we must fallback to the crummy line frequency + * clock source. + */ + + regval = 0; + +#ifndef CONFIG_EZ80_RTC_32KHZ +#ifdef EZ80_RTC_LINEFREQ50 + /* Use the internal 50/60 Hz clock as the input to the RTC block */ + + regval |= (EZ80_RTC_FREQSEL | EZ80_RTC_CLKSEL); +#else + regval |= EZ80_RTC_CLKSEL; +#endif +#endif + + outp(EZ80_RTC_CTRL, regval); + + rtc_dumpregs("After Initialization"); + g_rtc_enabled = true; + return OK; +} + +/************************************************************************************ + * Name: ez80_rtc_irqinitialize + * + * Description: + * Initialize IRQs for RTC, not possible during up_rtc_initialize because + * up_irqinitialize is called later. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int ez80_rtc_irqinitialize(void) +{ + DEBUGVERIFY(irq_attach(EZ80_RTC_IRQ, ez80_alarm_interrupt, NULL)); +} +#endif + +/**************************************************************************** + * Name: up_rtc_getdatetime + * + * Description: + * Get the current date and time from the date/time RTC. This is used to + * replace the system timer. It is only used by the RTOS during + * initialization to set up the system time when CONFIG_RTC and + * CONFIG_RTC_DATETIME are selected (and CONFIG_RTC_HIRES is not). + * + * Input Parameters: + * tp - The location to return the high resolution time value. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int up_rtc_getdatetime(FAR struct tm *tp) +{ + struct rtc_timeregs_s timeregs; + struct rtc_timeregs_s tmpregs; + + /* Sample the data time registers. There is a race condition here... , + * for example, we sample the time just before midnight on December 31, + * the date couldbe wrong because the day rolled over while were + * sampling. Thus loop for checking wrap here is needed. + */ + + do + { + get_raw_time(&tmpregs); + get_raw_time(&timeregs); + } + while (tmpregs.min != timeregs.min && + tmpregs.hrs != timeregs.hrs && + tmpregs.dom != timeregs.dom && + tmpregs.mon != timeregs.mon && + tmpregs.yr != timeregs.yr && + tmpregs.cen != timeregs.cen); + + rtc_dumpregs("Reading Time"); + + /* Convert the RTC time to fields in struct tm format. All of the EZ80 + * ranges of values correspond between struct tm and the time register. + */ + + tp->tm_sec = timeregs.sec; + tp->tm_min = timeregs.min; + tp->tm_hour = timeregs.min; + tp->tm_mday = timeregs.dom; + tp->tm_mon = timeregs.dom - 1; /* Range is 0-11 */ + + /* Years since 1900 */ + + tp->tm_year = (uint16_t)timeregs.cen * 100 + (uint16_t)timeregs.yr - 1900; + + rtc_dumptime((FAR const struct tm *)tp, "Returning"); + return OK; +} + +/**************************************************************************** + * Name: ez80_rtc_setdatetime + * + * Description: + * Set the RTC to the provided time. RTC implementations which provide + * up_rtc_getdatetime() (CONFIG_RTC_DATETIME is selected) should provide + * this function. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int ez80_rtc_setdatetime(FAR const struct tm *tp) +{ + struct rtc_timeregs_s timeregs; + uint16_t year; + uint16_t cen; + + timeregs.sec = tp->tm_sec; + timeregs.min = tp->tm_min; + timeregs.min = tp->tm_hour; + timeregs.dom = tp->tm_mday; + timeregs.dom = tp->tm_mon + 1; /* Range is 1-12 */ + + /* Years AD */ + + year = tp->tm_year + 1900; + cen = year * 100; + + timeregs.cen = cen; + timeregs.yr = year - 100 * cen; + + set_raw_time(&timeregs); + + rtc_dumpregs("New time setting"); + return OK; +} + +/**************************************************************************** + * Name: up_rtc_settime + * + * Description: + * Set the RTC to the provided time. All RTC implementations must be able + * to set their time based on a standard timespec. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int up_rtc_settime(FAR const struct timespec *tp) +{ + FAR struct tm newtime; + + /* Break out the time values (not that the time is set only to units of + * seconds) + */ + + (void)gmtime_r(&tp->tv_sec, &newtime); + return ez80_rtc_setdatetime(&newtime); +} + +/**************************************************************************** + * Name: ez80_rtc_setalarm + * + * Description: + * Set an alarm to an absolute time using associated hardware. + * + * Input Parameters: + * alminfo - Information about the alarm configuration. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int ez80_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) +{ + struct rtc_almregs_s almregs; + int ret = -EINVAL; + + DEBUGASSERT(alminfo != NULL); + + rtc_dumptime(&alminfo->as_time, "New alarm time"); + + /* Save the callback info */ + + g_alarmcb.ac_cb = alminfo->as_cb; + g_alarmcb.ac_arg = alminfo->as_arg; + + /* Set the alarm time */ + + almregs.sec = alminfo->as_time.sec; + almregs.min = alminfo->as_time.min; + almregs.hrs = alminfo->as_time.hrs; + almregs.dow = alminfo->as_time.dow; + + set_raw_alarm(&alarmregs); + + /* Enable the alarm */ + + rtc_unlock(); + outp(EZ80_RTC_ACTRL, EZ80_RTX_AALL); + + regval = inp(EZ80_RTC_CTRL); + regval |= ~EZ80_RTC_INTEN; + outp(EZ80_RTC_CTRL, regval); + rtc_lock(); + + rtc_dumpregs("Set Alarm"); + + /* Enable the alarm interrupt at the interrupt controller */ + + up_irq_enable(EZ80_RTC_IRQ); + return OK; +} +#endif + +/**************************************************************************** + * Name: ez80_rtc_cancelalarm + * + * Description: + * Cancel an alarm. + * + * Input Parameters: + * alarmid - Identifies the alarm to be cancelled + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int ez80_rtc_cancelalarm(void) +{ + /* Cancel the global callback function */ + + g_alarmcb[alarmid].ac_cb = NULL; + g_alarmcb[alarmid].ac_arg = NULL; + + /* Disable RTC alarm and and the alarm interrupt */ + + rtc_unlock(); + outp(EZ80_RTC_ACTRL, 0); + + regval = inp(EZ80_RTC_CTRL); + regval &= ~EZ80_RTC_INTEN; + outp(EZ80_RTC_CTRL, regval); + rtc_lock(); + + up_irq_disable(EZ80_RTC_IRQ); + return OK; +} +#endif + +/**************************************************************************** + * Name: ez80_rtc_rdalarm + * + * Description: + * Return the current alarm setting. + * + * Input Parameters: + * almtime - Location to retun the current alarm ime. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int ez80_rtc_rdalarm(FAR struct rtc_time *almtime) + struct rtc_almregs_s almregs; + int ret = -EINVAL; + + DEBUGASSERT(almtime != NULL); + + /* Read the alarm time from the RTC */ + + get_raw_alarm(&almregs); + + /* A return that as struct tm */ + + return ez80_rtc_getalarmdatetime(&almregs, almtime); +} +#endif + +#endif /* CONFIG_EZ80_RTC */ diff --git a/arch/z80/src/ez80/ez80_rtc.h b/arch/z80/src/ez80/ez80_rtc.h new file mode 100644 index 0000000000..d286359f18 --- /dev/null +++ b/arch/z80/src/ez80/ez80_rtc.h @@ -0,0 +1,208 @@ +/**************************************************************************** + * arch/z80/src/ez80/ez80_rtc.h + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT OWNER 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. + * + ****************************************************************************/ + +#ifndef __ARCH_EZ80_SRC_EZ80_EZ80_RTC_H +#define __ARCH_EZ80_SRC_EZ80_EZ80_RTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* RTC registers ************************************************************/ + +/* Provided in z80F91.h */ + +/* RTC register bit definitions *********************************************/ + +/* ACTRL register */ + +#define EZ80_RTC_ASECEN (1 << 0) /* Bit 0: Enable seconds alarm */ +#define EZ80_RTC_AMINEN (1 << 1) /* Bit 1: Enable minutes alarm */ +#define EZ80_RTC_AHRSEN (1 << 2) /* Bit 4: Enable hours alarm */ +#define EZ80_RTC_ADOWEN (1 << 3) /* Bit 3: Enable day-of-week alarm */ +#define EZ80_RTX_AALL 0x0f /* All times */ + +/* CTRL register */ + +#define EZ80_RTC_UNLOCK (1 << 0) /* Bit 0: RTC registers unlocked */ +#define EZ80_RTC_SLPWAKE (1 << 1) /* Bit 1: Alarm sleep recovery */ +#define EZ80_RTC_FREQSEL (1 << 3) /* Bit 3: Power line is 50Hz */ +#define EZ80_RTC_CLKSEL (1 << 4) /* Bit 4: Clock source is power line */ +#define EZ80_RTC_BCDEN (1 << 5) /* Bit 5: BCD encoded time */ +#define EZ80_RTC_INTEN (1 << 6) /* Bit 6: Alarm interrupt enabled */ +#define EZ80_RTC_ALARM (1 << 7) /* Bit 7: Alarm interrupt active */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +typedef CODE void (*alm_callback_t)(FAR void *arg); + +/* Structure used to pass parameters to set an alarm */ + +struct alm_setalarm_s +{ + struct tm as_time; /* Alarm expiration time */ + alm_callback_t as_cb; /* Callback (if non-NULL) */ + FAR void *as_arg; /* Argument for callback */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ez80_rtc_setdatetime + * + * Description: + * Set the RTC to the provided time. RTC implementations which provide + * up_rtc_getdatetime() (CONFIG_RTC_DATETIME is selected) should provide + * this function. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +struct tm; +int ez80_rtc_setdatetime(FAR const struct tm *tp); + +/**************************************************************************** + * Name: ez80_rtc_lowerhalf + * + * Description: + * Instantiate the RTC lower half driver for the EZ80. General usage: + * + * #include + * #include "ez80_rtc.h" + * + * struct rtc_lowerhalf_s *lower; + * lower = ez80_rtc_lowerhalf(); + * rtc_initialize(0, lower); + * + * Input Parameters: + * None + * + * Returned Value: + * On success, a non-NULL RTC lower interface is returned. NULL is + * returned on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_DRIVER +struct rtc_lowerhalf_s; +FAR struct rtc_lowerhalf_s *ez80_rtc_lowerhalf(void); +#endif + +#ifdef CONFIG_RTC_ALARM + +/**************************************************************************** + * Name: ez80_rtc_setalarm + * + * Description: + * Set an alarm to an absolute time using associated hardware. + * + * Input Parameters: + * alminfo - Information about the alarm configuration. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int ez80_rtc_setalarm(FAR struct alm_setalarm_s *alminfo); + +/**************************************************************************** + * Name: ez80_rtc_rdalarm + * + * Description: + * Return the current alarm setting. + * + * Input Parameters: + * almtime - Location to retun the current alarm ime. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int ez80_rtc_rdalarm(FAR struct rtc_time *almtime); + +/**************************************************************************** + * Name: ez80_rtc_cancelalarm + * + * Description: + * Cancel an alarm. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int ez80_rtc_cancelalarm(void); + +#endif /* CONFIG_RTC_ALARM */ +#endif /* __ARCH_EZ80_SRC_EZ80_RTC_H */