summaryrefslogblamecommitdiffstats
path: root/bsps/arm/lpc32xx/rtc/rtc-config.c
blob: 484c23f6f44724a1f722e85c176102a42b7f5220 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11

                                           


        
                               




                            

                                                                      



















                                                                              



                        
                
                        
                                  
 

                 













                                               

                                         
                                                          
 



                                                       


                                                             
                             





                                   


                                            

                     


                                             




                           
                                           



                        



                                     




                                                               



                                                                  
                        
                                 














                                    



                                                                        
                                        














                                             
                                     
 












                                         
/* SPDX-License-Identifier: BSD-2-Clause */

/**
 * @file
 *
 * @ingroup RTEMSBSPsARMLPC32XX
 *
 * @brief RTC configuration.
 */

/*
 * Copyright (c) 2009-2011 embedded brains GmbH.  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 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.
 */

#include <libchip/rtc.h>

#include <bsp.h>
#include <bsp/lpc32xx.h>
#include <rtems/rtems/clockimpl.h>

#include <time.h>

#define LPC32XX_RTC_COUNT 1U

#define LPC32XX_RTC_COUNTER_DELTA 0xfffffffeU

#define LPC32XX_RTC_KEY 0xb5c13f27U

#define LPC32XX_RTC_CTRL_FORCE_ONSW (1U << 7)
#define LPC32XX_RTC_CTRL_STOP (1U << 6)
#define LPC32XX_RTC_CTRL_RESET (1U << 4)
#define LPC32XX_RTC_CTRL_MATCH_1_ONSW (1U << 3)
#define LPC32XX_RTC_CTRL_MATCH_0_ONSW (1U << 2)
#define LPC32XX_RTC_CTRL_MATCH_1_INTR (1U << 1)
#define LPC32XX_RTC_CTRL_MATCH_0_INTR (1U << 0)

static void lpc32xx_rtc_set(uint32_t val)
{
  unsigned i = lpc32xx_arm_clk() / LPC32XX_OSCILLATOR_RTC;

  lpc32xx.rtc.ctrl |= LPC32XX_RTC_CTRL_STOP;
  lpc32xx.rtc.ucount = val;
  lpc32xx.rtc.dcount = LPC32XX_RTC_COUNTER_DELTA - val;
  lpc32xx.rtc.ctrl &= ~LPC32XX_RTC_CTRL_STOP;

  /* It needs some time before we can read the values back */
  while (i != 0) {
    __asm__ volatile ("nop");
    --i;
  }
}

static void lpc32xx_rtc_reset(void)
{
  lpc32xx.rtc.ctrl = LPC32XX_RTC_CTRL_RESET;
  lpc32xx.rtc.ctrl = 0;
  lpc32xx.rtc.key = LPC32XX_RTC_KEY;
  lpc32xx_rtc_set(0);
}

static void lpc32xx_rtc_initialize(int minor)
{
  uint32_t up_first = 0;
  uint32_t up_second = 0;
  uint32_t down_first = 0;
  uint32_t down_second = 0;

  if (lpc32xx.rtc.key != LPC32XX_RTC_KEY) {
    lpc32xx_rtc_reset();
  }

  do {
    up_first = lpc32xx.rtc.ucount;
    down_first = lpc32xx.rtc.dcount;
    up_second = lpc32xx.rtc.ucount;
    down_second = lpc32xx.rtc.dcount;
  } while (up_first != up_second || down_first != down_second);

  if (up_first + down_first != LPC32XX_RTC_COUNTER_DELTA) {
    lpc32xx_rtc_reset();
  }
}

static int lpc32xx_rtc_get_time(int minor, rtems_time_of_day *tod)
{
  struct timeval now = {
    .tv_sec = lpc32xx.rtc.ucount,
    .tv_usec = 0
  };
  struct tm time;

  gmtime_r(&now.tv_sec, &time);

  tod->year   = time.tm_year + 1900;
  tod->month  = time.tm_mon + 1;
  tod->day    = time.tm_mday;
  tod->hour   = time.tm_hour;
  tod->minute = time.tm_min;
  tod->second = time.tm_sec;
  tod->ticks  = 0;

  return RTEMS_SUCCESSFUL;
}

static int lpc32xx_rtc_set_time(int minor, const rtems_time_of_day *tod)
{
  lpc32xx_rtc_set(_TOD_To_seconds(tod));

  return 0;
}

static bool lpc32xx_rtc_probe(int minor)
{
  return true;
}

const rtc_fns lpc32xx_rtc_ops = {
  .deviceInitialize = lpc32xx_rtc_initialize,
  .deviceGetTime = lpc32xx_rtc_get_time,
  .deviceSetTime = lpc32xx_rtc_set_time
};

size_t RTC_Count = LPC32XX_RTC_COUNT;

rtc_tbl	RTC_Table [LPC32XX_RTC_COUNT] = {
  {
    .sDeviceName = "/dev/rtc",
    .deviceType = RTC_CUSTOM,
    .pDeviceFns = &lpc32xx_rtc_ops,
    .deviceProbe = lpc32xx_rtc_probe,
    .pDeviceParams = NULL,
    .ulCtrlPort1 = 0,
    .ulDataPort = 0,
    .getRegister = NULL,
    .setRegister = NULL
  }
};