drv_rtc.c 4.6 KB
Newer Older
D
Du Huanpeng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 * Copyright (c) 2020, Du Huanpeng <548708880@qq.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-01-30     armink       the first version
 * 2020-06-23     Du Huanpeng  based on components/drivers/rtc/soft_rtc.c
 */


#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
17
#include <sys/time.h>
D
Du Huanpeng 已提交
18 19
#include "ls2k1000.h"

20 21
#ifdef RT_USING_RTC

0
0xcccccccccccc 已提交
22 23
struct loongson_rtc
{
D
Du Huanpeng 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
    rt_uint32_t sys_toytrim;
    rt_uint32_t sys_toywrite0;
    rt_uint32_t sys_toywrite1;
    rt_uint32_t sys_toyread0;
    rt_uint32_t sys_toyread1;
    rt_uint32_t sys_toymatch0;
    rt_uint32_t sys_toymatch1;
    rt_uint32_t sys_toymatch2;
    rt_uint32_t sys_rtcctrl;
    rt_uint32_t __pad4[3];
    rt_uint32_t __pad5[4];
    rt_uint32_t sys_rtctrim;
    rt_uint32_t sys_rtcwrite0;
    rt_uint32_t sys_rtcread0;
    rt_uint32_t sys_rtcmatch0;
    rt_uint32_t sys_rtcmatch1;
    rt_uint32_t sys_rtcmatch2;
};

/* bit field helpers. */
#define __M(n)               (~(~0<<(n)))
#define __RBF(number, n)     ((number)&__M(n))
#define __BF(number, n, m)   __RBF((number>>m), (n-m+1))
#define BF(number, n, m)     (m<n ? __BF(number, n, m) : __BF(number, m, n))

0
0xcccccccccccc 已提交
49 50
struct rtctime
{
D
Du Huanpeng 已提交
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
    rt_uint32_t sys_toyread0;
    rt_uint32_t sys_toyread1;
    rt_uint32_t sys_rtcread0;
};
typedef struct rtctime rtctime_t;

struct tm *localrtctime(const rtctime_t *rtctp)
{
    static struct tm time;
    int msec;

    msec = BF(rtctp->sys_toyread0, 3, 0);
    msec *= 100;

    time.tm_sec   = BF(rtctp->sys_toyread0,  9,  4);
    time.tm_min   = BF(rtctp->sys_toyread0, 15, 10);
    time.tm_hour  = BF(rtctp->sys_toyread0, 20, 16);
    time.tm_mday  = BF(rtctp->sys_toyread0, 21, 25);
    time.tm_mon   = BF(rtctp->sys_toyread0, 26, 31);
    /* struct tm has three more members:
         time.tm_isdst
         time.tm_wday
         time.tm_yday
    */
    time.tm_mon -= 1;
    time.tm_year = rtctp->sys_toyread1;
    return &time;
}

rtctime_t mkrtctime(struct tm *tm)
{
    rtctime_t rtctm;
    struct tm tmptime;

    rtctm.sys_toyread0 <<= 31 - 26 + 1;
    rtctm.sys_toyread0  |= tm->tm_mon + 1;
    rtctm.sys_toyread0 <<= 25 - 21 + 1;
    rtctm.sys_toyread0  |= tm->tm_mday;
    rtctm.sys_toyread0 <<= 20 - 16 + 1;
    rtctm.sys_toyread0  |= tm->tm_hour;
    rtctm.sys_toyread0 <<= 15 - 10 + 1;
    rtctm.sys_toyread0  |= tm->tm_min;
    rtctm.sys_toyread0 <<= 9 - 4 + 1;
    rtctm.sys_toyread0  |= tm->tm_sec;
    /* Fixme: 0.1 second */
    rtctm.sys_toyread0 <<= 3 - 0 + 1;
    rtctm.sys_toyread0  |= 0;

    rtctm.sys_toyread1 = tm->tm_year;

    tmptime = *localrtctime(&rtctm);

    return rtctm;
}

static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag)
{
    return RT_EOK;
}

0
0xcccccccccccc 已提交
111
static rt_size_t rt_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
D
Du Huanpeng 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
{
    return 0;
}

static rt_err_t rt_rtc_ioctl(rt_device_t dev, int cmd, void *args)
{
    rt_err_t err = RT_ENOSYS;

    static int count = 0;

    struct loongson_rtc *hw_rtc;
    rtctime_t rtctm;
    struct tm time;
    struct tm tmptime;
    time_t *t;

    hw_rtc = dev->user_data;

    t = (time_t *)args;
mysterywolf's avatar
mysterywolf 已提交
131
    time = *gmtime(t);
D
Du Huanpeng 已提交
132 133 134 135 136 137

    rtctm.sys_toyread0 = hw_rtc->sys_toyread0;
    rtctm.sys_toyread1 = hw_rtc->sys_toyread1;
    rtctm.sys_rtcread0 = hw_rtc->sys_rtcread0;
    tmptime = *localrtctime(&rtctm);

0
0xcccccccccccc 已提交
138 139
    switch (cmd)
    {
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
        case RT_DEVICE_CTRL_RTC_GET_TIME:
            *t = timegm(&tmptime);
            break;
        case RT_DEVICE_CTRL_RTC_SET_TIME:
            tmptime.tm_hour = time.tm_hour;
            tmptime.tm_min  = time.tm_min;
            tmptime.tm_sec  = time.tm_sec;

            tmptime.tm_year = time.tm_year;
            tmptime.tm_mon  = time.tm_mon;
            tmptime.tm_mday = time.tm_mday;

            rtctm = mkrtctime(&tmptime);
            /* write to hw RTC */
            hw_rtc->sys_toywrite0 = rtctm.sys_toyread0;
            hw_rtc->sys_toywrite1 = rtctm.sys_toyread1;
            break;
        case RT_DEVICE_CTRL_RTC_GET_ALARM:
            break;
        case RT_DEVICE_CTRL_RTC_SET_ALARM:
            break;
        default:
            break;
D
Du Huanpeng 已提交
163 164 165 166 167 168 169
    }

    return RT_EOK;
}

int rt_hw_rtc_init(void)
{
0
0xcccccccccccc 已提交
170 171
    static struct rt_device rtc =
    {
D
Du Huanpeng 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184
        .type      = RT_Device_Class_RTC,
        .init      = RT_NULL,
        .open      = rt_rtc_open,
        .close     = RT_NULL,
        .read      = rt_rtc_read,
        .write     = RT_NULL,
        .control   = rt_rtc_ioctl,
        .user_data = (void *)RTC_BASE,
    };
    rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR);
}

INIT_DEVICE_EXPORT(rt_hw_rtc_init);
185 186

#endif /*RT_USING_RTC*/