; 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 ; Note - debug stuff won't work since we don't get passed a HAL workspace pointer! ; IMPORT DebugHALPrint ; IMPORT DebugHALPrintReg ; IMPORT DebugMemDump ; IMPORT DebugHALPrintByte ; TWL/TPS RTC IIC address TPSRTC_IIC * &4b ; Some RTC registers SECONDS_REG * &1C RTC_CTRL_REG * &29 RTC_STATUS_REG * &2a MACRO CallOS $entry, $tailcall ASSERT $entry <= HighestOSEntry [ "$tailcall"="" MOV lr, pc | [ "$tailcall"<>"tailcall" ! 0, "Unrecognised parameter to CallOS" ] ] LDR pc, OSentries + 4*$entry MEND RTC_Init ; Just register our HAL Device with the OS MOV a1, #0 ADR a2, RTCDevice CallOS OS_AddDevice, tailcall RTCDevice 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 ; todo - add RTCFormatFlags_BCD_NeedsYearHelp once NVRAM is implemented % 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 ; a3 = IICOp func ptr ; a4 = kernel workspace ptr ; Out: ; a1 = return code ; RTCTimeStruct updated Push "v1-v3,lr" MOV v1, a3 MOV v2, a4 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, #ECOMPLETED LDRB ip, [a2] MOV a1, #RTCRetCode_InvalidTime MOVNE a1, #RTCRetCode_Error EOR ip, ip, #2 TSTEQ ip, #2 ADDNE sp, sp, #4 Pull "v1-v3,pc", NE MOV ip, #&41 STR ip, [a2] MOV a1, #TPSRTC_IIC*2 MOV a4, #RTC_CTRL_REG BL TPSWrite CMP a1, #ECOMPLETED MOVNE a1, #RTCRetCode_Error ADD sp, sp, #4 Pull "v1-v3,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, #ECOMPLETED MOVNE a1, #RTCRetCode_Error Pull "v1-v3,pc", NE ASSERT ECOMPLETED = 0 STRB a1, [v3, #RTCTimeStruct_BCD_Centiseconds] ; No centisecond time ; Construct a fakey YearHI by looking at YearLO ; Anything 70 or above is considered 1970+, else 2000+ ; This should work OK, since RISC OS clamps the time to 1970 for unix compatability (or it does on boot, at least) LDRB a2, [v3, #RTCTimeStruct_BCD_YearLO] CMP a2, #&70 MOVGE a3, #&19 MOVLT a3, #&20 STRB a3, [v3, #RTCTimeStruct_BCD_YearHI] ASSERT RTCRetCode_OK = 0 Pull "v1-v3,pc" RTCWriteTime ; In: ; a1 = HALDevice ptr ; a2 = RTCTimeStruct ptr ; a3 = IICOp func ptr ; a4 = kernel workspace ptr ; Out: ; a1 = return code Push "v1-v3,lr" MOV v1, a3 MOV v2, a4 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, #ECOMPLETED MOVNE a1, #RTCRetCode_Error ADDNE sp, sp, #4 Pull "v1-v3,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, #ECOMPLETED MOVNE a1, #RTCRetCode_Error ADDNE sp, sp, #4 Pull "v1-v3,pc", NE 01 MOV a3, #1 STR a3, [sp] MOV a2, sp MOV a4, #RTC_CTRL_REG MOV a1, #TPSRTC_IIC*2 BL TPSWrite CMP a1, #ECOMPLETED ASSERT RTCRetCode_OK = ECOMPLETED MOVNE a1, #RTCRetCode_Error ADD sp, sp, #4 Pull "v1-v3,pc" EXPORT ReadTimeForNVRAM IMPORT IIC_DoOp_Poll ; int ReadTimeForNVRAM (struct rtctime*) ; Reads BCD time into given rtctime struct ; Returns zero on success, non-zero on failure ReadTimeForNVRAM MOV a2, a1 ADRL a1, RTCDevice LDR a3, HALInitialised CMP a3, #0 ADREQL a3, IIC_DoOp_Poll LDRNE a3, OSentries + 4 * OS_IICOpV B RTCReadTime END