RTC 8.41 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
; Copyright 2009 Castle Technology Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
Robert Sprowson's avatar
Robert Sprowson committed
15

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
        GET     Hdr:ListOpts
        GET     Hdr:Macros
        GET     Hdr:System
        GET     Hdr:Machine.<Machine>
        GET     Hdr:ImageSize.<ImageSize>
        $GetIO

        GET     Hdr:OSEntries
        GET     Hdr:HALEntries
        GET     Hdr:HALDevice
        GET     Hdr:RTCDevice

        GET     hdr.omap3530
        GET     hdr.StaticWS
        GET     hdr.Timers
        GET     hdr.PRCM

        AREA    |Asm$$Code|, CODE, READONLY, PIC

        EXPORT  RTC_Init
36 37
        IMPORT  TPSRead
        IMPORT  TPSWrite
38
        IMPORT  memcpy
39

40
; TWL/TPS RTC IIC address
41
TPSRTC_IIC        * &4b
42 43 44 45 46 47

; Some RTC registers
SECONDS_REG       * &1C
RTC_CTRL_REG      * &29
RTC_STATUS_REG    * &2a

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
; RTC_CTRL_REG bitfields
RTC_CTRL_STOP_RTC_M             *       (1 << 0)
RTC_CTRL_ROUND_30S_M            *       (1 << 1)
RTC_CTRL_AUTO_COMP_M            *       (1 << 2)
RTC_CTRL_MODE_12_24_M           *       (1 << 3)
RTC_CTRL_TEST_MODE_M            *       (1 << 4)
RTC_CTRL_SET_32_COUNTER_M       *       (1 << 5)
RTC_CTRL_GET_TIME_M             *       (1 << 6)

; RTC_STATUS_REG bitfields
RTC_STATUS_RUN_M                *       (1 << 1)
RTC_STATUS_1S_EVENT_M           *       (1 << 2)
RTC_STATUS_1M_EVENT_M           *       (1 << 3)
RTC_STATUS_1H_EVENT_M           *       (1 << 4)
RTC_STATUS_1D_EVENT_M           *       (1 << 5)
RTC_STATUS_ALARM_M              *       (1 << 6)
RTC_STATUS_POWER_UP_M           *       (1 << 7)
65 66 67

RTC_Init
        ; Just register our HAL Device with the OS
68 69 70 71 72 73 74 75
        ADRL    a1, RTCWS
        ADR     a2, RTCDeviceTemplate
        MOV     a3, #RTCSize
        Push    "lr"
        BL      memcpy
        Pull    "lr"
        STR     sb, [a1, #RTCDeviceHAL_SB]

76 77 78 79
        MOV     a1, #0
        ADR     a2, RTCDevice
        CallOS  OS_AddDevice, tailcall

80
RTCDeviceTemplate
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
        DCW     HALDeviceType_SysPeri + HALDeviceSysPeri_RTC
        DCW     HALDeviceID_RTC_TPS65950
        DCD     HALDeviceBus_Ser + HALDeviceSerBus_IIC
        DCD     0               ; API version
        DCD     RTCDesc
        DCD     0               ; Address - N/A
        %       12              ; Reserved
        DCD     RTCActivate
        DCD     RTCDeactivate
        DCD     RTCReset
        DCD     RTCSleep
        DCD     -1              ; Interrupt N/A
        DCD     0
        %       8
        DCB     RTCTimeFormat_BCD
96 97 98 99
        DCB     RTCFormatFlags_BCD_1BasedDay + \
                RTCFormatFlags_BCD_1BasedMonth + \
                RTCFormatFlags_BCD_YearLOIsGood + \
                RTCFormatFlags_BCD_NeedsYearHelp
100 101 102 103 104
        %       2
        DCD     RTCReadTime
        DCD     RTCWriteTime

RTCDesc
105
        DCB     "TPS65950-compatible real-time clock",0
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

        ALIGN

RTCActivate
        MOV     a1, #1
RTCDeactivate
RTCReset
        MOV     pc, lr

RTCSleep
        MOV     a1, #0 ; Previously at full power
        MOV     pc, lr

RTCReadTime
        ; In:
        ; a1 = HALDevice ptr
        ; a2 = RTCTimeStruct ptr
        ; Out:
        ; a1 = return code
        ; RTCTimeStruct updated
126 127 128
        Push    "v1,v3,sb,lr"
        LDR     sb, [a1, #RTCDeviceHAL_SB]
        LDR     v1, OSentries+4*OS_IICOpV ; for TPSRead/TPSWrite
129 130
        MOV     v3, a2
        ; Reading the time safely involves several transfers:
131 132 133 134 135
        ; 1. Read RTC_STATUS_REG. If bit 1 is clear, the RTC is stopped and we can just
        ;    assume its contents are invalid.
        ; 2. Set RTC_CTRL_REG=&41 (RTC running, GET_TIME set, 24hr mode). GET_TIME will read
        ;    the time from the RTC circuitry and latch it into the time registers (the regular
        ;    time registers, NOT the alarm ones as stated by the manual!)
136 137
        ; 3. Read the time regs to read latched time.
        ; There's no need to clear GET_TIME either, as it is cleared automatically by the HW.
138
        MOV     a1, #TPSRTC_IIC*2
139 140
        SUB     sp, sp, #4 ; temp small buffer on stack
        MOV     a3, #1
141
        MOV     a4, #RTC_STATUS_REG
142 143
        MOV     a2, sp
        BL      TPSRead
144
        CMP     a1, #IICStatus_Completed
145 146 147
        LDRB    ip, [a2]
        MOV     a1, #RTCRetCode_InvalidTime
        MOVNE   a1, #RTCRetCode_Error
148 149
        EOR     ip, ip, #RTC_STATUS_RUN_M
        TSTEQ   ip, #RTC_STATUS_RUN_M
150
        ADDNE   sp, sp, #4
151 152
        Pull    "v1,v3,sb,pc", NE
        MOV     ip, #(RTC_CTRL_GET_TIME_M + RTC_CTRL_STOP_RTC_M)
153
        STR     ip, [a2]
154 155
        MOV     a1, #TPSRTC_IIC*2
        MOV     a4, #RTC_CTRL_REG
156
        BL      TPSWrite
157
        CMP     a1, #IICStatus_Completed
158 159
        MOVNE   a1, #RTCRetCode_Error
        ADD     sp, sp, #4
160
        Pull    "v1,v3,sb,pc", NE
161
        MOV     a1, #TPSRTC_IIC*2
162 163 164 165 166 167 168 169
        ; We can read the time directly into the RTCTimeStruct buffer
        ASSERT RTCTimeStruct_BCD_Minutes=RTCTimeStruct_BCD_Seconds+1
        ASSERT RTCTimeStruct_BCD_Hours=RTCTimeStruct_BCD_Seconds+2
        ASSERT RTCTimeStruct_BCD_DayOfMonth=RTCTimeStruct_BCD_Seconds+3
        ASSERT RTCTimeStruct_BCD_Month=RTCTimeStruct_BCD_Seconds+4
        ASSERT RTCTimeStruct_BCD_YearLO=RTCTimeStruct_BCD_Seconds+5
        ADD     a2, v3, #RTCTimeStruct_BCD_Seconds
        MOV     a3, #6
170
        MOV     a4, #SECONDS_REG
171
        BL      TPSRead
172
        CMP     a1, #IICStatus_Completed
173
        MOVNE   a1, #RTCRetCode_Error
174
        ASSERT  IICStatus_Completed = 0
175 176
        STREQB  a1, [v3, #RTCTimeStruct_BCD_Centiseconds] ; No centisecond time
        STREQB  a1, [v3, #RTCTimeStruct_BCD_YearHI] ; Kernel gives year help
177
        ASSERT  RTCRetCode_OK = 0
178
        Pull    "v1,v3,sb,pc"
179 180 181 182 183 184 185

RTCWriteTime
        ; In:
        ; a1 = HALDevice ptr
        ; a2 = RTCTimeStruct ptr
        ; Out:
        ; a1 = return code
186 187 188
        Push    "v1,v3,sb,lr"
        LDR     sb, [a1, #RTCDeviceHAL_SB]
        LDR     v1, OSentries+4*OS_IICOpV ; for TPSRead/TPSWrite
189 190
        MOV     v3, a2
        ; Writing the time safely involves several transfers:
191 192
        ; 1. Write 0 to RTC_CTRL_REG to stop the clock (just in case there are any issues with
        ;    the clock updating while it's being written to)
193 194
        ; 2. Write the new time values
        ; 3. Write 1 to RTC_CTRL_REG to start the clock
195
        MOV     a1, #TPSRTC_IIC*2
196 197 198
        MOV     ip, #0
        STR     ip, [sp,#-4]! ; temp small buffer on stack
        MOV     a3, #1
199
        MOV     a4, #RTC_CTRL_REG
200 201
        MOV     a2, sp
        BL      TPSWrite
202
        CMP     a1, #IICStatus_Completed
203 204
        MOVNE   a1, #RTCRetCode_Error
        ADDNE   sp, sp, #4
205
        Pull    "v1,v3,sb,pc", NE
206
        MOV     a1, #TPSRTC_IIC*2
207 208 209 210 211 212 213 214
        ; We can write the time directly from the RTCTimeStruct buffer
        ASSERT RTCTimeStruct_BCD_Minutes=RTCTimeStruct_BCD_Seconds+1
        ASSERT RTCTimeStruct_BCD_Hours=RTCTimeStruct_BCD_Seconds+2
        ASSERT RTCTimeStruct_BCD_DayOfMonth=RTCTimeStruct_BCD_Seconds+3
        ASSERT RTCTimeStruct_BCD_Month=RTCTimeStruct_BCD_Seconds+4
        ASSERT RTCTimeStruct_BCD_YearLO=RTCTimeStruct_BCD_Seconds+5
        ADD     a2, v3, #RTCTimeStruct_BCD_Seconds
        MOV     a3, #6
215
        MOV     a4, #SECONDS_REG
216 217 218 219 220 221 222 223 224 225 226
        ; Sometimes we don't write the time, so skip those bytes if necessary
        LDRB    ip, [a2]
        CMP     ip, #255
        ADDEQ   a2, a2, #3
        SUBEQ   a3, a3, #3
        ADDEQ   a4, a4, #3
        ; Sometimes we don't write the date either
        LDRB    ip, [v3, #RTCTimeStruct_BCD_DayOfMonth]
        CMP     ip, #255
        SUBEQS  a3, a3, #3
        BEQ     %FT01 ; Nothing left to write!
227
        BL      TPSWrite
228
        CMP     a1, #IICStatus_Completed
229 230
        MOVNE   a1, #RTCRetCode_Error
        ADDNE   sp, sp, #4
231
        Pull    "v1,v3,sb,pc", NE
232
01
233
        MOV     a3, #RTC_CTRL_STOP_RTC_M
234 235
        STR     a3, [sp]
        MOV     a2, sp
236 237
        MOV     a4, #RTC_CTRL_REG
        MOV     a1, #TPSRTC_IIC*2
238
        BL      TPSWrite
239 240
        CMP     a1, #IICStatus_Completed
        ASSERT  RTCRetCode_OK = IICStatus_Completed
241 242
        MOVNE   a1, #RTCRetCode_Error
        ADD     sp, sp, #4
243
        Pull    "v1,v3,sb,pc"
244 245

        END