; 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. ; 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 IMPORT TPSRead IMPORT TPSWrite IMPORT memcpy ; TWL/TPS RTC IIC address TPSRTC_IIC * &4b ; Some RTC registers SECONDS_REG * &1C RTC_CTRL_REG * &29 RTC_STATUS_REG * &2a ; 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) RTC_Init ; Just register our HAL Device with the OS ADRL a1, RTCWS ADR a2, RTCDeviceTemplate MOV a3, #RTCSize Push "lr" BL memcpy Pull "lr" STR sb, [a1, #RTCDeviceHAL_SB] MOV a2, a1 MOV a1, #0 CallOS OS_AddDevice, tailcall RTCDeviceTemplate 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 DCB RTCFormatFlags_BCD_1BasedDay + \ RTCFormatFlags_BCD_1BasedMonth + \ RTCFormatFlags_BCD_YearLOIsGood + \ RTCFormatFlags_BCD_NeedsYearHelp % 2 DCD RTCReadTime DCD RTCWriteTime RTCDesc DCB "TPS65950-compatible real-time clock",0 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 Push "v1,v3,sb,lr" LDR sb, [a1, #RTCDeviceHAL_SB] LDR v1, OSentries+4*OS_IICOpV ; for TPSRead/TPSWrite MOV v3, a2 ; Reading the time safely involves several transfers: ; 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!) ; 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. MOV a1, #TPSRTC_IIC*2 SUB sp, sp, #4 ; temp small buffer on stack MOV a3, #1 MOV a4, #RTC_STATUS_REG MOV a2, sp BL TPSRead CMP a1, #IICStatus_Completed LDRB ip, [a2] MOV a1, #RTCRetCode_InvalidTime MOVNE a1, #RTCRetCode_Error EOR ip, ip, #RTC_STATUS_RUN_M TSTEQ ip, #RTC_STATUS_RUN_M ADDNE sp, sp, #4 Pull "v1,v3,sb,pc", NE MOV ip, #(RTC_CTRL_GET_TIME_M + RTC_CTRL_STOP_RTC_M) STR ip, [a2] MOV a1, #TPSRTC_IIC*2 MOV a4, #RTC_CTRL_REG BL TPSWrite CMP a1, #IICStatus_Completed MOVNE a1, #RTCRetCode_Error ADD sp, sp, #4 Pull "v1,v3,sb,pc", NE MOV a1, #TPSRTC_IIC*2 ; 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 MOV a4, #SECONDS_REG BL TPSRead CMP a1, #IICStatus_Completed MOVNE a1, #RTCRetCode_Error ASSERT IICStatus_Completed = 0 STREQB a1, [v3, #RTCTimeStruct_BCD_Centiseconds] ; No centisecond time STREQB a1, [v3, #RTCTimeStruct_BCD_YearHI] ; Kernel gives year help ASSERT RTCRetCode_OK = 0 Pull "v1,v3,sb,pc" RTCWriteTime ; In: ; a1 = HALDevice ptr ; a2 = RTCTimeStruct ptr ; Out: ; a1 = return code Push "v1,v3,sb,lr" LDR sb, [a1, #RTCDeviceHAL_SB] LDR v1, OSentries+4*OS_IICOpV ; for TPSRead/TPSWrite MOV v3, a2 ; Writing the time safely involves several transfers: ; 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) ; 2. Write the new time values ; 3. Write 1 to RTC_CTRL_REG to start the clock MOV a1, #TPSRTC_IIC*2 MOV ip, #0 STR ip, [sp,#-4]! ; temp small buffer on stack MOV a3, #1 MOV a4, #RTC_CTRL_REG MOV a2, sp BL TPSWrite CMP a1, #IICStatus_Completed MOVNE a1, #RTCRetCode_Error ADDNE sp, sp, #4 Pull "v1,v3,sb,pc", NE MOV a1, #TPSRTC_IIC*2 ; 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 MOV a4, #SECONDS_REG ; 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! BL TPSWrite CMP a1, #IICStatus_Completed MOVNE a1, #RTCRetCode_Error ADDNE sp, sp, #4 Pull "v1,v3,sb,pc", NE 01 MOV a3, #RTC_CTRL_STOP_RTC_M STR a3, [sp] MOV a2, sp MOV a4, #RTC_CTRL_REG MOV a1, #TPSRTC_IIC*2 BL TPSWrite CMP a1, #IICStatus_Completed ASSERT RTCRetCode_OK = IICStatus_Completed MOVNE a1, #RTCRetCode_Error ADD sp, sp, #4 Pull "v1,v3,sb,pc" END